{"thread":{"id":"626","subject":"Re: Darcs-git: a few notes for Git hackers","startedAt":"2005-05-15T09:11:41Z","lastAt":"2005-05-17T20:21:50Z","messageCount":9,"participants":["Brad Roberts","Petr Baudis","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"3350","messageId":"Pine.LNX.4.44.0505150208020.2136-200000@bellevue.puremagic.com","threadId":"626","inReplyTo":"Pine.LNX.4.44.0505141851340.2136-200000@bellevue.puremagic.com","subject":"Re: Darcs-git: a few notes for Git hackers","fromName":"Brad Roberts","fromEmail":"braddr@puremagic.com","sentAt":"2005-05-15T09:11:41Z","receivedAt":"2005-05-15T09:11:41Z","isPatch":false,"sender":{"key":"braddr@puremagic.com","avatar":null},"body":"Resending, I left off the mailing list on the to list last time.\n\n> > I wasn't able to finish redoing these against linus tip, but I got most of\n> > it done (patches 1-14 of the original 19):\n> >\n> >   http://gameboy2.puremagic.com:8090/\n> >   rsync://gameboy2.puremagic.com/git/\n> >\n> > The second, third, and forth to last changes need a careful review,\n> > they're direct applications of the original patches which were lightly\n> > tested during the first round and nothing other than compile tested in\n> > this round.\n> >\n> > I suspect the remaining parts of the original patch series will go in\n> > fairly smoothly.  If no one gets to them before tonight I'll finish\n> > it up after work.\n> >\n> > Later,\n> > Brad\n>\n> I've completed the re-merge, and moved to tip of git-pb.git rather than\n> tip of git.git.  Unfortunatly that merge was also somewhat intrusive and\n> my individual diffs along the way are somewhat useless now.  The entire\n> history is available about the above locations still.  Attached is the\n> full diff vs git-pb @ 902b92e00e491a60d55c4b2bce122903b8347f34.\n>\n> The unit tests that are being added are a wonderful thing, thanks so much\n> for doing them Junio.\n>\n> These changes feel rough to me still.  Some areas to discuss / think\n> about:\n>\n> 1) The hunks that change the merge routines from pointer based to index\n> based could have been left much less intruded upon by adding a\n> get_cache_entry_array(cache) api.\n>\n> 2) Should the index changing areas be constructing a new index instead of\n> shuffling bits within the current index?\n>\n> 3) The vocabulary and code is inconsistent between cache and index.\n>\n> 4) read-cache.c does much more than reading.\n>\n> 5) Like before, cleaning up memory for the cache is a rarity, preferring\n> to let the end of the process garbage collect everything.\n>\n>  cache.h          |   52 ++++++-------\n>  check-files.c    |   12 +--\n>  checkout-cache.c |   26 +++---\n>  diff-cache.c     |   60 ++++++++-------\n>  diff-files.c     |   31 ++++---\n>  diff-helper.c    |    6 -\n>  diff-tree.c      |   50 ++++++------\n>  diff.c           |   36 +++++----\n>  diff.h           |   11 +-\n>  fsck-cache.c     |    6 -\n>  local-pull.c     |    2\n>  ls-files.c       |   47 ++++++-----\n>  merge-cache.c    |   29 +++----\n>  read-cache.c     |  217 ++++++++++++++++++++++++++++++++++---------------------\n>  read-tree.c      |   65 +++++++++-------\n>  sha1_file.c      |    4 -\n>  tree.c           |   15 ++-\n>  update-cache.c   |   45 +++++------\n>  write-tree.c     |   29 ++++---\n>  19 files changed, 416 insertions(+), 327 deletions(-)\n>\n> Signed-off-by: Brad Roberts <braddr@puremagic.com>\n>\n>\n\n\n\nIndex: cache.h\n===================================================================\n--- c8c77f67ea85ee65a0f055f2cb76e6059eaa0776/cache.h  (mode:100644)\n+++ uncommitted/cache.h  (mode:100644)\n@@ -40,19 +40,8 @@\n \n /*\n  * Basic data structures for the directory cache\n- *\n- * NOTE NOTE NOTE! This is all in the native CPU byte format. It's\n- * not even trying to be portable. It's trying to be efficient. It's\n- * just a cache, after all.\n  */\n \n-#define CACHE_SIGNATURE 0x44495243\t/* \"DIRC\" */\n-struct cache_header {\n-\tunsigned int hdr_signature;\n-\tunsigned int hdr_version;\n-\tunsigned int hdr_entries;\n-};\n-\n /*\n  * The \"cache_time\" is just the low 32 bits of the\n  * time. It doesn't matter if it overflows - we only\n@@ -89,6 +78,9 @@\n #define CE_STAGEMASK (0x3000)\n #define CE_STAGESHIFT 12\n \n+extern int ce_match_stat(struct cache_entry *ce, struct stat *st);\n+extern int ce_same_name(struct cache_entry *a, struct cache_entry *b);\n+\n #define create_ce_flags(len, stage) htons((len) | ((stage) << CE_STAGESHIFT))\n #define ce_namelen(ce) (CE_NAMEMASK & ntohs((ce)->ce_flags))\n #define ce_size(ce) cache_entry_size(ce_namelen(ce))\n@@ -104,9 +96,6 @@\n \n #define cache_entry_size(len) ((offsetof(struct cache_entry,name) + (len) + 8) & ~7)\n \n-extern struct cache_entry **active_cache;\n-extern unsigned int active_nr, active_alloc, active_cache_changed;\n-\n #define GIT_DIR_ENVIRONMENT \"GIT_DIR\"\n #define DEFAULT_GIT_DIR_ENVIRONMENT \".git\"\n #define DB_ENVIRONMENT \"GIT_OBJECT_DIRECTORY\"\n@@ -120,17 +109,19 @@\n #define alloc_nr(x) (((x)+16)*3/2)\n \n /* Initialize and use the cache information */\n-extern int read_cache(void);\n-extern int write_cache(int newfd, struct cache_entry **cache, int entries);\n-extern int cache_name_pos(const char *name, int namelen);\n+extern struct cache *new_cache(void);\n+extern struct cache *read_cache(void);\n+extern int write_cache(struct cache *cache, int newfd);\n+extern void free_cache(struct cache *cache);\n+extern int cache_name_pos(struct cache *cache, const char *name, int namelen);\n #define ADD_CACHE_OK_TO_ADD 1\t\t/* Ok to add */\n #define ADD_CACHE_OK_TO_REPLACE 2\t/* Ok to replace file/directory */\n-extern int add_cache_entry(struct cache_entry *ce, int option);\n-extern int remove_entry_at(int pos);\n-extern int remove_file_from_cache(char *path);\n-extern int same_name(struct cache_entry *a, struct cache_entry *b);\n-extern int cache_match_stat(struct cache_entry *ce, struct stat *st);\n-extern int index_fd(unsigned char *sha1, int fd, struct stat *st);\n+extern int add_cache_entry(struct cache *cache, struct cache_entry *ce, int option);\n+extern int remove_file_from_cache(struct cache *cache, char *path);\n+extern int get_num_cache_entries(struct cache *cache);\n+extern struct cache_entry *get_cache_entry(struct cache *cache, int pos);\n+extern void set_cache_entry(struct cache *cache, struct cache_entry *ce, int pos);\n+extern int remove_cache_entry_at(struct cache *cache, int pos);\n \n #define MTIME_CHANGED\t0x0001\n #define CTIME_CHANGED\t0x0002\n@@ -148,11 +139,12 @@\n extern void * unpack_sha1_file(void *map, unsigned long mapsize, char *type, unsigned long *size);\n extern void * read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size);\n extern int write_sha1_file(char *buf, unsigned long len, const char *type, unsigned char *return_sha1);\n+extern int index_fd(unsigned char *sha1, int fd, struct stat *st);\n \n extern int check_sha1_signature(unsigned char *sha1, void *buf, unsigned long size, const char *type);\n \n /* Read a tree into the cache */\n-extern int read_tree(void *buffer, unsigned long size, int stage);\n+extern int read_tree(struct cache *cache, void *buffer, unsigned long size, int stage);\n \n extern int write_sha1_from_fd(const unsigned char *sha1, int fd);\n \n@@ -179,7 +171,7 @@\n void parse_date(char *date, char *buf, int bufsize);\n void datestamp(char *buf, int bufsize);\n \n-static inline void *xmalloc(int size)\n+static inline void *xmalloc(size_t size)\n {\n \tvoid *ret = malloc(size);\n \tif (!ret)\n@@ -187,7 +179,7 @@\n \treturn ret;\n }\n \n-static inline void *xrealloc(void *ptr, int size)\n+static inline void *xrealloc(void *ptr, size_t size)\n {\n \tvoid *ret = realloc(ptr, size);\n \tif (!ret)\n@@ -195,4 +187,12 @@\n \treturn ret;\n }\n \n+static inline void *xcalloc(size_t nmemb, size_t size)\n+{\n+\tvoid *ret = calloc(nmemb, size);\n+\tif (!ret)\n+\t\tdie(\"Out of memory, calloc failed\");\n+\treturn ret;\n+}\n+\n #endif /* CACHE_H */\nIndex: check-files.c\n===================================================================\n--- c8c77f67ea85ee65a0f055f2cb76e6059eaa0776/check-files.c  (mode:100644)\n+++ uncommitted/check-files.c  (mode:100644)\n@@ -8,7 +8,7 @@\n  */\n #include \"cache.h\"\n \n-static void check_file(const char *path)\n+static void check_file(struct cache *cache, const char *path)\n {\n \tint fd = open(path, O_RDONLY);\n \tstruct cache_entry *ce;\n@@ -23,15 +23,15 @@\n \t}\n \n \t/* Exists but is not in the cache is not fine */\n-\tpos = cache_name_pos(path, strlen(path));\n+\tpos = cache_name_pos(cache, path, strlen(path));\n \tif (pos < 0)\n \t\tdie(\"preparing to update existing file '%s' not in cache\", path);\n-\tce = active_cache[pos];\n+\tce = get_cache_entry(cache, pos);\n \n \tif (lstat(path, &st) < 0)\n \t\tdie(\"lstat(%s): %s\", path, strerror(errno));\n \n-\tchanged = cache_match_stat(ce, &st);\n+\tchanged = ce_match_stat(ce, &st);\n \tif (changed)\n \t\tdie(\"preparing to update file '%s' not uptodate in cache\", path);\n }\n@@ -39,9 +39,9 @@\n int main(int argc, char **argv)\n {\n \tint i;\n+\tstruct cache *cache = read_cache();\n \n-\tread_cache();\n \tfor (i = 1; i < argc ; i++)\n-\t\tcheck_file(argv[i]);\n+\t\tcheck_file(cache, argv[i]);\n \treturn 0;\n }\nIndex: checkout-cache.c\n===================================================================\n--- c8c77f67ea85ee65a0f055f2cb76e6059eaa0776/checkout-cache.c  (mode:100644)\n+++ uncommitted/checkout-cache.c  (mode:100644)\n@@ -167,7 +167,7 @@\n \tstrcpy(path + len, ce->name);\n \n \tif (!lstat(path, &st)) {\n-\t\tunsigned changed = cache_match_stat(ce, &st);\n+\t\tunsigned changed = ce_match_stat(ce, &st);\n \t\tif (!changed)\n \t\t\treturn 0;\n \t\tif (!force) {\n@@ -188,30 +188,30 @@\n \treturn write_entry(ce, path);\n }\n \n-static int checkout_file(const char *name, const char *base_dir)\n+static int checkout_file(struct cache *cache, const char *name, const char *base_dir)\n {\n-\tint pos = cache_name_pos(name, strlen(name));\n+\tint pos = cache_name_pos(cache, name, strlen(name));\n \tif (pos < 0) {\n \t\tif (!quiet) {\n \t\t\tpos = -pos - 1;\n \t\t\tfprintf(stderr,\n \t\t\t\t\"checkout-cache: %s is %s.\\n\",\n \t\t\t\tname,\n-\t\t\t\t(pos < active_nr &&\n-\t\t\t\t !strcmp(active_cache[pos]->name, name)) ?\n+\t\t\t\t(pos < get_num_cache_entries(cache) &&\n+\t\t\t\t !strcmp(get_cache_entry(cache, pos)->name, name)) ?\n \t\t\t\t\"unmerged\" : \"not in the cache\");\n \t\t}\n \t\treturn -1;\n \t}\n-\treturn checkout_entry(active_cache[pos], base_dir);\n+\treturn checkout_entry(get_cache_entry(cache, pos), base_dir);\n }\n \n-static int checkout_all(const char *base_dir)\n+static int checkout_all(struct cache *cache, const char *base_dir)\n {\n \tint i;\n \n-\tfor (i = 0; i < active_nr ; i++) {\n-\t\tstruct cache_entry *ce = active_cache[i];\n+\tfor (i = 0; i < get_num_cache_entries(cache) ; i++) {\n+\t\tstruct cache_entry *ce = get_cache_entry(cache, i);\n \t\tif (ce_stage(ce))\n \t\t\tcontinue;\n \t\tif (checkout_entry(ce, base_dir) < 0)\n@@ -225,15 +225,15 @@\n \tint i, force_filename = 0;\n \tconst char *base_dir = \"\";\n \n-\tif (read_cache() < 0) {\n+\tstruct cache *cache = read_cache();\n+\tif (!cache) \n \t\tdie(\"invalid cache\");\n-\t}\n \n \tfor (i = 1; i < argc; i++) {\n \t\tconst char *arg = argv[i];\n \t\tif (!force_filename) {\n \t\t\tif (!strcmp(arg, \"-a\")) {\n-\t\t\t\tcheckout_all(base_dir);\n+\t\t\t\tcheckout_all(cache, base_dir);\n \t\t\t\tcontinue;\n \t\t\t}\n \t\t\tif (!strcmp(arg, \"--\")) {\n@@ -257,7 +257,7 @@\n \t\t\t\tcontinue;\n \t\t\t}\n \t\t}\n-\t\tcheckout_file(arg, base_dir);\n+\t\tcheckout_file(cache, arg, base_dir);\n \t}\n \treturn 0;\n }\nIndex: diff-cache.c\n===================================================================\n--- c8c77f67ea85ee65a0f055f2cb76e6059eaa0776/diff-cache.c  (mode:100644)\n+++ uncommitted/diff-cache.c  (mode:100644)\n@@ -7,10 +7,10 @@\n static int line_termination = '\\n';\n \n /* A file entry went away or appeared */\n-static void show_file(const char *prefix, struct cache_entry *ce, unsigned char *sha1, unsigned int mode)\n+static void show_file(struct cache *cache, const char *prefix, struct cache_entry *ce, unsigned char *sha1, unsigned int mode)\n {\n \tif (generate_patch)\n-\t\tdiff_addremove(prefix[0], ntohl(mode), sha1, ce->name, NULL);\n+\t\tdiff_addremove(cache, prefix[0], ntohl(mode), sha1, ce->name, NULL);\n \telse\n \t\tprintf(\"%s%06o\\tblob\\t%s\\t%s%c\", prefix, ntohl(mode),\n \t\t       sha1_to_hex(sha1), ce->name, line_termination);\n@@ -33,7 +33,7 @@\n \t\t\t}\n \t\t\treturn -1;\n \t\t}\n-\t\tchanged = cache_match_stat(ce, &st);\n+\t\tchanged = ce_match_stat(ce, &st);\n \t\tif (changed) {\n \t\t\tmode = create_ce_mode(st.st_mode);\n \t\t\tsha1 = no_sha1;\n@@ -45,7 +45,7 @@\n \treturn 0;\n }\n \n-static void show_new_file(struct cache_entry *new)\n+static void show_new_file(struct cache *cache, struct cache_entry *new)\n {\n \tunsigned char *sha1;\n \tunsigned int mode;\n@@ -54,10 +54,11 @@\n \tif (get_stat_data(new, &sha1, &mode) < 0)\n \t\treturn;\n \n-\tshow_file(\"+\", new, sha1, mode);\n+\tshow_file(cache, \"+\", new, sha1, mode);\n }\n \n-static int show_modified(struct cache_entry *old,\n+static int show_modified(struct cache *cache,\n+\t\t\t struct cache_entry *old,\n \t\t\t struct cache_entry *new,\n \t\t\t int report_missing)\n {\n@@ -67,7 +68,7 @@\n \n \tif (get_stat_data(new, &sha1, &mode) < 0) {\n \t\tif (report_missing)\n-\t\t\tshow_file(\"-\", old, old->sha1, old->ce_mode);\n+\t\t\tshow_file(cache, \"-\", old, old->sha1, old->ce_mode);\n \t\treturn -1;\n \t}\n \n@@ -79,7 +80,7 @@\n \toldmode = ntohl(oldmode);\n \n \tif (generate_patch)\n-\t\tdiff_change(oldmode, mode,\n+\t\tdiff_change(cache, oldmode, mode,\n \t\t\t    old->sha1, sha1, old->name, NULL);\n \telse {\n \t\tstrcpy(old_sha1_hex, sha1_to_hex(old->sha1));\n@@ -90,30 +91,34 @@\n \treturn 0;\n }\n \n-static int diff_cache(struct cache_entry **ac, int entries)\n+static int diff_cache(struct cache *cache)\n {\n-\twhile (entries) {\n-\t\tstruct cache_entry *ce = *ac;\n-\t\tint same = (entries > 1) && same_name(ce, ac[1]);\n+\tint pos = 0, num = get_num_cache_entries(cache);\n+\n+\twhile (pos < num) {\n+\t\tstruct cache_entry *ce = get_cache_entry(cache, pos);\n+\t\tstruct cache_entry *ce_next = ((pos+1) < num) ?\n+\t\t\tget_cache_entry(cache, pos+1) : NULL;\n+\t\tint same = ce_next && ce_same_name(ce, ce_next);\n \n \t\tswitch (ce_stage(ce)) {\n \t\tcase 0:\n \t\t\t/* No stage 1 entry? That means it's a new file */\n \t\t\tif (!same) {\n-\t\t\t\tshow_new_file(ce);\n+\t\t\t\tshow_new_file(cache, ce);\n \t\t\t\tbreak;\n \t\t\t}\n \t\t\t/* Show difference between old and new */\n-\t\t\tshow_modified(ac[1], ce, 1);\n+\t\t\tshow_modified(cache, ce_next, ce, 1);\n \t\t\tbreak;\n \t\tcase 1:\n \t\t\t/* No stage 3 (merge) entry? That means it's been deleted */\n \t\t\tif (!same) {\n-\t\t\t\tshow_file(\"-\", ce, ce->sha1, ce->ce_mode);\n+\t\t\t\tshow_file(cache, \"-\", ce, ce->sha1, ce->ce_mode);\n \t\t\t\tbreak;\n \t\t\t}\n \t\t\t/* We come here with ce pointing at stage 1\n-\t\t\t * (original tree) and ac[1] pointing at stage\n+\t\t\t * (original tree) and ce_next pointing at stage\n \t\t\t * 3 (unmerged).  show-modified with\n \t\t\t * report-mising set to false does not say the\n \t\t\t * file is deleted but reports true if work\n@@ -122,12 +127,12 @@\n \t\t\t * Otherwise, we show the differences between\n \t\t\t * the original tree and the work tree.\n \t\t\t */\n-\t\t\tif (!cached_only && !show_modified(ce, ac[1], 0))\n+\t\t\tif (!cached_only && !show_modified(cache, ce, ce_next, 0))\n \t\t\t\tbreak;\n \t\t\t/* fallthru */\n \t\tcase 3:\n \t\t\tif (generate_patch)\n-\t\t\t\tdiff_unmerge(ce->name);\n+\t\t\t\tdiff_unmerge(cache, ce->name);\n \t\t\telse\n \t\t\t\tprintf(\"U %s%c\", ce->name, line_termination);\n \t\t\tbreak;\n@@ -141,9 +146,8 @@\n \t\t * we've handled the relevant cases now.\n \t\t */\n \t\tdo {\n-\t\t\tac++;\n-\t\t\tentries--;\n-\t\t} while (entries && same_name(ce, ac[0]));\n+\t\t\tpos++;\n+\t\t} while (pos < num && ce_same_name(ce, get_cache_entry(cache, pos)));\n \t}\n \treturn 0;\n }\n@@ -153,11 +157,11 @@\n  * when we read in the new tree (into \"stage 1\"), we won't lose sight\n  * of the fact that we had unmerged entries.\n  */\n-static void mark_merge_entries(void)\n+static void mark_merge_entries(struct cache *cache)\n {\n \tint i;\n-\tfor (i = 0; i < active_nr; i++) {\n-\t\tstruct cache_entry *ce = active_cache[i];\n+\tfor (i = 0; i < get_num_cache_entries(cache); i++) {\n+\t\tstruct cache_entry *ce = get_cache_entry(cache, i);\n \t\tif (!ce_stage(ce))\n \t\t\tcontinue;\n \t\tce->ce_flags |= htons(CE_STAGEMASK);\n@@ -172,8 +176,8 @@\n \tunsigned char tree_sha1[20];\n \tvoid *tree;\n \tunsigned long size;\n+\tstruct cache * cache = read_cache();\n \n-\tread_cache();\n \twhile (argc > 2) {\n \t\tchar *arg = argv[1];\n \t\targv++;\n@@ -204,13 +208,13 @@\n \tif (argc != 2 || get_sha1(argv[1], tree_sha1))\n \t\tusage(diff_cache_usage);\n \n-\tmark_merge_entries();\n+\tmark_merge_entries(cache);\n \n \ttree = read_object_with_reference(tree_sha1, \"tree\", &size, 0);\n \tif (!tree)\n \t\tdie(\"bad tree object %s\", argv[1]);\n-\tif (read_tree(tree, size, 1))\n+\tif (read_tree(cache, tree, size, 1))\n \t\tdie(\"unable to read tree object %s\", argv[1]);\n \n-\treturn diff_cache(active_cache, active_nr);\n+\treturn diff_cache(cache);\n }\nIndex: diff-files.c\n===================================================================\n--- c8c77f67ea85ee65a0f055f2cb76e6059eaa0776/diff-files.c  (mode:100644)\n+++ uncommitted/diff-files.c  (mode:100644)\n@@ -28,18 +28,18 @@\n \treturn 0;\n }\n \n-static void show_unmerge(const char *path)\n+static void show_unmerge(struct cache *cache, const char *path)\n {\n \tif (generate_patch)\n-\t\tdiff_unmerge(path);\n+\t\tdiff_unmerge(cache, path);\n \telse\n \t\tprintf(\"U %s%c\", path, line_termination);\n }\n \n-static void show_file(int pfx, struct cache_entry *ce)\n+static void show_file(struct cache *cache, int pfx, struct cache_entry *ce)\n {\n \tif (generate_patch)\n-\t\tdiff_addremove(pfx, ntohl(ce->ce_mode), ce->sha1,\n+\t\tdiff_addremove(cache, pfx, ntohl(ce->ce_mode), ce->sha1,\n \t\t\t       ce->name, NULL);\n \telse\n \t\tprintf(\"%c%06o\\t%s\\t%s\\t%s%c\",\n@@ -47,7 +47,7 @@\n \t\t       sha1_to_hex(ce->sha1), ce->name, line_termination);\n }\n \n-static void show_modified(int oldmode, int mode,\n+static void show_modified(struct cache *cache, int oldmode, int mode,\n \t\t\t  const char *old_sha1, const char *sha1,\n \t\t\t  char *path)\n {\n@@ -55,7 +55,7 @@\n \tstrcpy(old_sha1_hex, sha1_to_hex(old_sha1));\n \n \tif (generate_patch)\n-\t\tdiff_change(oldmode, mode, old_sha1, sha1, path, NULL);\n+\t\tdiff_change(cache, oldmode, mode, old_sha1, sha1, path, NULL);\n \telse\n \t\tprintf(\"*%06o->%06o\\tblob\\t%s->%s\\t%s%c\",\n \t\t       oldmode, mode, old_sha1_hex, sha1_to_hex(sha1), path,\n@@ -65,7 +65,8 @@\n int main(int argc, char **argv)\n {\n \tstatic const char null_sha1[20] = { 0, };\n-\tint entries = read_cache();\n+\tstruct cache *cache = read_cache();\n+\tint entries;\n \tint i;\n \n \twhile (1 < argc && argv[1][0] == '-') {\n@@ -87,15 +88,17 @@\n \t/* At this point, if argc == 1, then we are doing everything.\n \t * Otherwise argv[1] .. argv[argc-1] have the explicit paths.\n \t */\n-\tif (entries < 0) {\n+\tif (!cache) {\n \t\tperror(\"read_cache\");\n \t\texit(1);\n \t}\n \n+\tentries = get_num_cache_entries(cache);\n+\n \tfor (i = 0; i < entries; i++) {\n \t\tstruct stat st;\n \t\tunsigned int oldmode, mode;\n-\t\tstruct cache_entry *ce = active_cache[i];\n+\t\tstruct cache_entry *ce = get_cache_entry(cache, i);\n \t\tint changed;\n \n \t\tif (1 < argc &&\n@@ -103,9 +106,9 @@\n \t\t\tcontinue;\n \n \t\tif (ce_stage(ce)) {\n-\t\t\tshow_unmerge(ce->name);\n+\t\t\tshow_unmerge(cache, ce->name);\n \t\t\twhile (i < entries &&\n-\t\t\t       !strcmp(ce->name, active_cache[i]->name))\n+\t\t\t       !strcmp(ce->name, get_cache_entry(cache, i)->name))\n \t\t\t\ti++;\n \t\t\ti--; /* compensate for loop control increments */\n \t\t\tcontinue;\n@@ -118,10 +121,10 @@\n \t\t\t}\t\n \t\t\tif (silent)\n \t\t\t\tcontinue;\n-\t\t\tshow_file('-', ce);\n+\t\t\tshow_file(cache, '-', ce);\n \t\t\tcontinue;\n \t\t}\n-\t\tchanged = cache_match_stat(ce, &st);\n+\t\tchanged = ce_match_stat(ce, &st);\n \t\tif (!changed)\n \t\t\tcontinue;\n \n@@ -129,7 +132,7 @@\n \t\tmode = (S_ISLNK(st.st_mode) ? S_IFLNK :\n \t\t\tS_IFREG | ce_permissions(st.st_mode));\n \n-\t\tshow_modified(oldmode, mode, ce->sha1, null_sha1,\n+\t\tshow_modified(cache, oldmode, mode, ce->sha1, null_sha1,\n \t\t\t      ce->name);\n \t}\n \treturn 0;\nIndex: diff-helper.c\n===================================================================\n--- c8c77f67ea85ee65a0f055f2cb76e6059eaa0776/diff-helper.c  (mode:100644)\n+++ uncommitted/diff-helper.c  (mode:100644)\n@@ -56,7 +56,7 @@\n \tswitch (*cp++) {\n \tcase 'U':\n \t\tif (!cnt || matches_pathspec(cp + 1, spec, cnt))\n-\t\t\tdiff_unmerge(cp + 1);\n+\t\t\tdiff_unmerge(NULL, cp + 1);\n \t\treturn 0;\n \tcase '+':\n \t\told.file_valid = 0;\n@@ -102,9 +102,9 @@\n \t}\n \tif (!cnt || matches_pathspec(path, spec, cnt)) {\n \t\tif (reverse)\n-\t\t\trun_external_diff(path, &new, &old);\n+\t\t\trun_external_diff(NULL, path, &new, &old);\n \t\telse\n-\t\t\trun_external_diff(path, &old, &new);\n+\t\t\trun_external_diff(NULL, path, &old, &new);\n \t}\n \treturn 0;\n }\nIndex: diff-tree.c\n===================================================================\n--- c8c77f67ea85ee65a0f055f2cb76e6059eaa0776/diff-tree.c  (mode:100644)\n+++ uncommitted/diff-tree.c  (mode:100644)\n@@ -17,7 +17,7 @@\n static char **paths = NULL;\n static int *pathlens = NULL;\n \n-static int diff_tree_sha1(const unsigned char *old, const unsigned char *new, const char *base);\n+static int diff_tree_sha1(struct cache *cache, const unsigned char *old, const unsigned char *new, const char *base);\n \n static void update_tree_entry(void **bufp, unsigned long *sizep)\n {\n@@ -53,19 +53,19 @@\n \treturn newbase;\n }\n \n-static void show_file(const char *prefix, void *tree, unsigned long size, const char *base);\n+static void show_file(struct cache *cache, const char *prefix, void *tree, unsigned long size, const char *base);\n \n /* A whole sub-tree went away or appeared */\n-static void show_tree(const char *prefix, void *tree, unsigned long size, const char *base)\n+static void show_tree(struct cache *cache, const char *prefix, void *tree, unsigned long size, const char *base)\n {\n \twhile (size) {\n-\t\tshow_file(prefix, tree, size, base);\n+\t\tshow_file(cache, prefix, tree, size, base);\n \t\tupdate_tree_entry(&tree, &size);\n \t}\n }\n \n /* A file entry went away or appeared */\n-static void show_file(const char *prefix, void *tree, unsigned long size, const char *base)\n+static void show_file(struct cache *cache, const char *prefix, void *tree, unsigned long size, const char *base)\n {\n \tunsigned mode;\n \tconst char *path;\n@@ -89,7 +89,7 @@\n \t\tif (!tree || strcmp(type, \"tree\"))\n \t\t\tdie(\"corrupt tree sha %s\", sha1_to_hex(sha1));\n \n-\t\tshow_tree(prefix, tree, size, newbase);\n+\t\tshow_tree(cache, prefix, tree, size, newbase);\n \t\t\n \t\tfree(tree);\n \t\tfree(newbase);\n@@ -98,7 +98,7 @@\n \n \tif (generate_patch) {\n \t\tif (!S_ISDIR(mode))\n-\t\t\tdiff_addremove(prefix[0], mode, sha1, base, path);\n+\t\t\tdiff_addremove(cache, prefix[0], mode, sha1, base, path);\n \t}\n \telse\n \t\tprintf(\"%s%06o\\t%s\\t%s\\t%s%s%c\", prefix, mode,\n@@ -107,7 +107,7 @@\n \t\t       line_termination);\n }\n \n-static int compare_tree_entry(void *tree1, unsigned long size1, void *tree2, unsigned long size2, const char *base)\n+static int compare_tree_entry(struct cache *cache, void *tree1, unsigned long size1, void *tree2, unsigned long size2, const char *base)\n {\n \tunsigned mode1, mode2;\n \tconst char *path1, *path2;\n@@ -122,11 +122,11 @@\n \tpathlen2 = strlen(path2);\n \tcmp = cache_name_compare(path1, pathlen1, path2, pathlen2);\n \tif (cmp < 0) {\n-\t\tshow_file(\"-\", tree1, size1, base);\n+\t\tshow_file(cache, \"-\", tree1, size1, base);\n \t\treturn -1;\n \t}\n \tif (cmp > 0) {\n-\t\tshow_file(\"+\", tree2, size2, base);\n+\t\tshow_file(cache, \"+\", tree2, size2, base);\n \t\treturn 1;\n \t}\n \tif (!memcmp(sha1, sha2, 20) && mode1 == mode2)\n@@ -137,15 +137,15 @@\n \t * file, we need to consider it a remove and an add.\n \t */\n \tif (S_ISDIR(mode1) != S_ISDIR(mode2)) {\n-\t\tshow_file(\"-\", tree1, size1, base);\n-\t\tshow_file(\"+\", tree2, size2, base);\n+\t\tshow_file(cache, \"-\", tree1, size1, base);\n+\t\tshow_file(cache, \"+\", tree2, size2, base);\n \t\treturn 0;\n \t}\n \n \tif (recursive && S_ISDIR(mode1)) {\n \t\tint retval;\n \t\tchar *newbase = malloc_base(base, path1, pathlen1);\n-\t\tretval = diff_tree_sha1(sha1, sha2, newbase);\n+\t\tretval = diff_tree_sha1(cache, sha1, sha2, newbase);\n \t\tfree(newbase);\n \t\treturn retval;\n \t}\n@@ -159,7 +159,7 @@\n \n \tif (generate_patch) {\n \t\tif (!S_ISDIR(mode1))\n-\t\t\tdiff_change(mode1, mode2, sha1, sha2, base, path1);\n+\t\t\tdiff_change(cache, mode1, mode2, sha1, sha2, base, path1);\n \t}\n \telse {\n \t\tstrcpy(old_sha1_hex, sha1_to_hex(sha1));\n@@ -217,7 +217,7 @@\n \treturn 0; /* No matches */\n }\n \n-static int diff_tree(void *tree1, unsigned long size1, void *tree2, unsigned long size2, const char *base)\n+static int diff_tree(struct cache *cache, void *tree1, unsigned long size1, void *tree2, unsigned long size2, const char *base)\n {\n \twhile (size1 | size2) {\n \t\tif (nr_paths && size1 && !interesting(tree1, size1, base)) {\n@@ -229,16 +229,16 @@\n \t\t\tcontinue;\n \t\t}\n \t\tif (!size1) {\n-\t\t\tshow_file(\"+\", tree2, size2, base);\n+\t\t\tshow_file(cache, \"+\", tree2, size2, base);\n \t\t\tupdate_tree_entry(&tree2, &size2);\n \t\t\tcontinue;\n \t\t}\n \t\tif (!size2) {\n-\t\t\tshow_file(\"-\", tree1, size1, base);\n+\t\t\tshow_file(cache, \"-\", tree1, size1, base);\n \t\t\tupdate_tree_entry(&tree1, &size1);\n \t\t\tcontinue;\n \t\t}\n-\t\tswitch (compare_tree_entry(tree1, size1, tree2, size2, base)) {\n+\t\tswitch (compare_tree_entry(cache, tree1, size1, tree2, size2, base)) {\n \t\tcase -1:\n \t\t\tupdate_tree_entry(&tree1, &size1);\n \t\t\tcontinue;\n@@ -254,7 +254,7 @@\n \treturn 0;\n }\n \n-static int diff_tree_sha1(const unsigned char *old, const unsigned char *new, const char *base)\n+static int diff_tree_sha1(struct cache *cache, const unsigned char *old, const unsigned char *new, const char *base)\n {\n \tvoid *tree1, *tree2;\n \tunsigned long size1, size2;\n@@ -266,7 +266,7 @@\n \ttree2 = read_object_with_reference(new, \"tree\", &size2, 0);\n \tif (!tree2)\n \t\tdie(\"unable to read destination tree (%s)\", sha1_to_hex(new));\n-\tretval = diff_tree(tree1, size1, tree2, size2, base);\n+\tretval = diff_tree(cache, tree1, size1, tree2, size2, base);\n \tfree(tree1);\n \tfree(tree2);\n \treturn retval;\n@@ -342,7 +342,7 @@\n \treturn this_header;\n }\n \n-static int diff_tree_stdin(char *line)\n+static int diff_tree_stdin(struct cache *cache, char *line)\n {\n \tint len = strlen(line);\n \tunsigned char commit[20], parent[20];\n@@ -360,7 +360,7 @@\n \t\tline[81] = 0;\n \t\tsprintf(this_header, \"%s (from %s)\\n\", line, line+41);\n \t\theader = this_header;\n-\t\treturn diff_tree_sha1(parent, commit, \"\");\n+\t\treturn diff_tree_sha1(cache, parent, commit, \"\");\n \t}\n \tbuf = read_object_with_reference(commit, \"commit\", &size, NULL);\n \tif (!buf)\n@@ -378,7 +378,7 @@\n \t\tif (get_sha1_hex(buf + offset + 7, parent))\n \t\t\treturn -1;\n \t\theader = generate_header(line, sha1_to_hex(parent), buf, size);\n-\t\tdiff_tree_sha1(parent, commit, \"\");\n+\t\tdiff_tree_sha1(cache, parent, commit, \"\");\n \t\tif (!header && verbose_header)\n \t\t\theader_prefix = \"\\ndiff-tree \";\n \t\toffset += 48;\n@@ -458,10 +458,10 @@\n \t}\n \n \tif (!read_stdin)\n-\t\treturn diff_tree_sha1(old, new, \"\");\n+\t\treturn diff_tree_sha1(NULL, old, new, \"\");\n \n \twhile (fgets(line, sizeof(line), stdin))\n-\t\tdiff_tree_stdin(line);\n+\t\tdiff_tree_stdin(NULL, line);\n \n \treturn 0;\n }\nIndex: diff.c\n===================================================================\n--- c8c77f67ea85ee65a0f055f2cb76e6059eaa0776/diff.c  (mode:100644)\n+++ uncommitted/diff.c  (mode:100644)\n@@ -147,7 +147,7 @@\n  * the work tree has that object contents, return true, so that\n  * prepare_temp_file() does not have to inflate and extract.\n  */\n-static int work_tree_matches(const char *name, const unsigned char *sha1)\n+static int work_tree_matches(struct cache *cache, const char *name, const unsigned char *sha1)\n {\n \tstruct cache_entry *ce;\n \tstruct stat st;\n@@ -165,17 +165,17 @@\n \t * by diff-cache --cached, which does read the cache before\n \t * calling us.\n \t */ \n-\tif (!active_cache)\n+\tif (!get_num_cache_entries(cache))\n \t\treturn 0;\n \n \tlen = strlen(name);\n-\tpos = cache_name_pos(name, len);\n+\tpos = cache_name_pos(cache, name, len);\n \tif (pos < 0)\n \t\treturn 0;\n-\tce = active_cache[pos];\n+\tce = get_cache_entry(cache, pos);\n \tif ((lstat(name, &st) < 0) ||\n \t    !S_ISREG(st.st_mode) ||\n-\t    cache_match_stat(ce, &st) ||\n+\t    ce_match_stat(ce, &st) ||\n \t    memcmp(sha1, ce->sha1, 20))\n \t\treturn 0;\n \treturn 1;\n@@ -202,7 +202,8 @@\n \tsprintf(temp->mode, \"%06o\", mode);\n }\n \n-static void prepare_temp_file(const char *name,\n+static void prepare_temp_file(struct cache *cache,\n+\t\t\t      const char *name,\n \t\t\t      struct diff_tempfile *temp,\n \t\t\t      struct diff_spec *one)\n {\n@@ -222,7 +223,7 @@\n \n \tif (one->sha1_valid &&\n \t    (!memcmp(one->blob_sha1, null_sha1, sizeof(null_sha1)) ||\n-\t     work_tree_matches(name, one->blob_sha1)))\n+\t     work_tree_matches(cache, name, one->blob_sha1)))\n \t\tuse_work_tree = 1;\n \n \tif (!one->sha1_valid || use_work_tree) {\n@@ -293,7 +294,8 @@\n  *               infile2 infile2-sha1 infile2-mode.\n  *\n  */\n-void run_external_diff(const char *name,\n+void run_external_diff(struct cache *cache,\n+\t\t       const char *name,\n \t\t       struct diff_spec *one,\n \t\t       struct diff_spec *two)\n {\n@@ -303,8 +305,8 @@\n \tstatic int atexit_asked = 0;\n \n \tif (one && two) {\n-\t\tprepare_temp_file(name, &temp[0], one);\n-\t\tprepare_temp_file(name, &temp[1], two);\n+\t\tprepare_temp_file(cache, name, &temp[0], one);\n+\t\tprepare_temp_file(cache, name, &temp[1], two);\n \t\tif (! atexit_asked &&\n \t\t    (temp[0].name == temp[0].tmp_path ||\n \t\t     temp[1].name == temp[1].tmp_path)) {\n@@ -357,7 +359,8 @@\n \tremove_tempfile();\n }\n \n-void diff_addremove(int addremove, unsigned mode,\n+void diff_addremove(struct cache *cache,\n+\t\t    int addremove, unsigned mode,\n \t\t    const unsigned char *sha1,\n \t\t    const char *base, const char *path)\n {\n@@ -379,10 +382,11 @@\n \t\tstrcpy(concatpath, base);\n \t\tstrcat(concatpath, path);\n \t}\n-\trun_external_diff(path ? concatpath : base, one, two);\n+\trun_external_diff(cache, path ? concatpath : base, one, two);\n }\n \n-void diff_change(unsigned old_mode, unsigned new_mode,\n+void diff_change(struct cache *cache,\n+\t\t unsigned old_mode, unsigned new_mode,\n \t\t const unsigned char *old_sha1,\n \t\t const unsigned char *new_sha1,\n \t\t const char *base, const char *path) {\n@@ -400,10 +404,10 @@\n \t\tstrcpy(concatpath, base);\n \t\tstrcat(concatpath, path);\n \t}\n-\trun_external_diff(path ? concatpath : base, &spec[0], &spec[1]);\n+\trun_external_diff(cache, path ? concatpath : base, &spec[0], &spec[1]);\n }\n \n-void diff_unmerge(const char *path)\n+void diff_unmerge(struct cache *cache, const char *path)\n {\n-\trun_external_diff(path, NULL, NULL);\n+\trun_external_diff(cache, path, NULL, NULL);\n }\nIndex: diff.h\n===================================================================\n--- c8c77f67ea85ee65a0f055f2cb76e6059eaa0776/diff.h  (mode:100644)\n+++ uncommitted/diff.h  (mode:100644)\n@@ -4,18 +4,20 @@\n #ifndef DIFF_H\n #define DIFF_H\n \n-extern void diff_addremove(int addremove,\n+extern void diff_addremove(struct cache *cache,\n+\t\t\t   int addremove,\n \t\t\t   unsigned mode,\n \t\t\t   const unsigned char *sha1,\n \t\t\t   const char *base,\n \t\t\t   const char *path);\n \n-extern void diff_change(unsigned mode1, unsigned mode2,\n+extern void diff_change(struct cache *cache,\n+\t\t\t     unsigned mode1, unsigned mode2,\n \t\t\t     const unsigned char *sha1,\n \t\t\t     const unsigned char *sha2,\n \t\t\t     const char *base, const char *path);\n \n-extern void diff_unmerge(const char *path);\n+extern void diff_unmerge(struct cache *cache, const char *path);\n \n /* These are for diff-helper */\n \n@@ -31,7 +33,8 @@\n \tunsigned file_valid : 1; /* if false the file does not even exist */\n };\n \n-extern void run_external_diff(const char *name,\n+extern void run_external_diff(struct cache *cache,\n+\t\t\t      const char *name,\n \t\t\t      struct diff_spec *, struct diff_spec *);\n \n #endif /* DIFF_H */\nIndex: fsck-cache.c\n===================================================================\n--- c8c77f67ea85ee65a0f055f2cb76e6059eaa0776/fsck-cache.c  (mode:100644)\n+++ uncommitted/fsck-cache.c  (mode:100644)\n@@ -356,9 +356,9 @@\n \n \tif (keep_cache_objects) {\n \t\tint i;\n-\t\tread_cache();\n-\t\tfor (i = 0; i < active_nr; i++) {\n-\t\t\tstruct blob *blob = lookup_blob(active_cache[i]->sha1);\n+\t\tstruct cache *cache = read_cache();\n+\t\tfor (i = 0; i < get_num_cache_entries(cache); i++) {\n+\t\t\tstruct blob *blob = lookup_blob(get_cache_entry(cache, i)->sha1);\n \t\t\tstruct object *obj;\n \t\t\tif (!blob)\n \t\t\t\tcontinue;\nIndex: local-pull.c\n===================================================================\n--- c8c77f67ea85ee65a0f055f2cb76e6059eaa0776/local-pull.c  (mode:100644)\n+++ uncommitted/local-pull.c  (mode:100644)\n@@ -61,7 +61,7 @@\n \t\t}\n \t\tmap = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, ifd, 0);\n \t\tclose(ifd);\n-\t\tif (-1 == (int)(long)map) {\n+\t\tif (MAP_FAILED == map) {\n \t\t\tfprintf(stderr, \"cannot mmap %s\\n\", filename);\n \t\t\treturn -1;\n \t\t}\nIndex: ls-files.c\n===================================================================\n--- c8c77f67ea85ee65a0f055f2cb76e6059eaa0776/ls-files.c  (mode:100644)\n+++ uncommitted/ls-files.c  (mode:100644)\n@@ -98,11 +98,11 @@\n static int nr_dir;\n static int dir_alloc;\n \n-static void add_name(const char *pathname, int len)\n+static void add_name(struct cache *cache, const char *pathname, int len)\n {\n \tstruct nond_on_fs *ent;\n \n-\tif (cache_name_pos(pathname, len) >= 0)\n+\tif (cache_name_pos(cache, pathname, len) >= 0)\n \t\treturn;\n \n \tif (nr_dir == dir_alloc) {\n@@ -124,7 +124,7 @@\n  * Also, we currently ignore all names starting with a dot.\n  * That likely will not change.\n  */\n-static void read_directory(const char *path, const char *base, int baselen)\n+static void read_directory(struct cache *cache, const char *path, const char *base, int baselen)\n {\n \tDIR *dir = opendir(path);\n \n@@ -157,14 +157,14 @@\n \t\t\t\t/* fallthrough */\n \t\t\tcase DT_DIR:\n \t\t\t\tmemcpy(fullname + baselen + len, \"/\", 2);\n-\t\t\t\tread_directory(fullname, fullname,\n+\t\t\t\tread_directory(cache, fullname, fullname,\n \t\t\t\t\t       baselen + len + 1);\n \t\t\t\tcontinue;\n \t\t\tcase DT_REG:\n \t\t\tcase DT_LNK:\n \t\t\t\tbreak;\n \t\t\t}\n-\t\t\tadd_name(fullname, baselen + len);\n+\t\t\tadd_name(cache, fullname, baselen + len);\n \t\t}\n \t\tclosedir(dir);\n \t}\n@@ -179,7 +179,7 @@\n \t\t\t\t  e2->name, e2->len);\n }\n \n-static void show_killed_files()\n+static void show_killed_files(struct cache *cache)\n {\n \tint i;\n \tfor (i = 0; i < nr_dir; i++) {\n@@ -193,28 +193,28 @@\n \t\t\t\t/* If ent->name is prefix of an entry in the\n \t\t\t\t * cache, it will be killed.\n \t\t\t\t */\n-\t\t\t\tpos = cache_name_pos(ent->name, ent->len);\n+\t\t\t\tpos = cache_name_pos(cache, ent->name, ent->len);\n \t\t\t\tif (0 <= pos)\n \t\t\t\t\tdie(\"bug in show-killed-files\");\n \t\t\t\tpos = -pos - 1;\n-\t\t\t\twhile (pos < active_nr &&\n-\t\t\t\t       ce_stage(active_cache[pos]))\n+\t\t\t\twhile (pos < get_num_cache_entries(cache) &&\n+\t\t\t\t       ce_stage(get_cache_entry(cache, pos)))\n \t\t\t\t\tpos++; /* skip unmerged */\n-\t\t\t\tif (active_nr <= pos)\n+\t\t\t\tif (get_num_cache_entries(cache) <= pos)\n \t\t\t\t\tbreak;\n \t\t\t\t/* pos points at a name immediately after\n \t\t\t\t * ent->name in the cache.  Does it expect\n \t\t\t\t * ent->name to be a directory?\n \t\t\t\t */\n-\t\t\t\tlen = ce_namelen(active_cache[pos]);\n+\t\t\t\tlen = ce_namelen(get_cache_entry(cache, pos));\n \t\t\t\tif ((ent->len < len) &&\n-\t\t\t\t    !strncmp(active_cache[pos]->name,\n+\t\t\t\t    !strncmp(get_cache_entry(cache, pos)->name,\n \t\t\t\t\t     ent->name, ent->len) &&\n-\t\t\t\t    active_cache[pos]->name[ent->len] == '/')\n+\t\t\t\t    get_cache_entry(cache, pos)->name[ent->len] == '/')\n \t\t\t\t\tkilled = 1;\n \t\t\t\tbreak;\n \t\t\t}\n-\t\t\tif (0 <= cache_name_pos(ent->name, sp - ent->name)) {\n+\t\t\tif (0 <= cache_name_pos(cache, ent->name, sp - ent->name)) {\n \t\t\t\t/* If any of the leading directories in\n \t\t\t\t * ent->name is registered in the cache,\n \t\t\t\t * ent->name will be killed.\n@@ -230,13 +230,13 @@\n \t}\n }\n \n-static void show_files(void)\n+static void show_files(struct cache *cache)\n {\n \tint i;\n \n \t/* For cached/deleted files we don't need to even do the readdir */\n \tif (show_others || show_killed) {\n-\t\tread_directory(\".\", \"\", 0);\n+\t\tread_directory(cache, \".\", \"\", 0);\n \t\tqsort(dir, nr_dir, sizeof(struct nond_on_fs *), cmp_name);\n \t\tif (show_others)\n \t\t\tfor (i = 0; i < nr_dir; i++)\n@@ -244,11 +244,11 @@\n \t\t\t\t       dir[i]->len, dir[i]->name,\n \t\t\t\t       line_terminator);\n \t\tif (show_killed)\n-\t\t\tshow_killed_files();\n+\t\t\tshow_killed_files(cache);\n \t}\n \tif (show_cached | show_stage) {\n-\t\tfor (i = 0; i < active_nr; i++) {\n-\t\t\tstruct cache_entry *ce = active_cache[i];\n+\t\tfor (i = 0; i < get_num_cache_entries(cache); i++) {\n+\t\t\tstruct cache_entry *ce = get_cache_entry(cache, i);\n \t\t\tif (excluded(ce->name) != show_ignored)\n \t\t\t\tcontinue;\n \t\t\tif (show_unmerged && !ce_stage(ce))\n@@ -269,8 +269,8 @@\n \t\t}\n \t}\n \tif (show_deleted) {\n-\t\tfor (i = 0; i < active_nr; i++) {\n-\t\t\tstruct cache_entry *ce = active_cache[i];\n+\t\tfor (i = 0; i < get_num_cache_entries(cache); i++) {\n+\t\t\tstruct cache_entry *ce = get_cache_entry(cache, i);\n \t\t\tstruct stat st;\n \t\t\tif (excluded(ce->name) != show_ignored)\n \t\t\t\tcontinue;\n@@ -289,6 +289,7 @@\n int main(int argc, char **argv)\n {\n \tint i;\n+\tstruct cache *cache;\n \n \tfor (i = 1; i < argc; i++) {\n \t\tchar *arg = argv[i];\n@@ -341,7 +342,7 @@\n \tif (!(show_stage | show_deleted | show_others | show_unmerged | show_killed))\n \t\tshow_cached = 1;\n \n-\tread_cache();\n-\tshow_files();\n+\tcache = read_cache();\n+\tshow_files(cache);\n \treturn 0;\n }\nIndex: merge-cache.c\n===================================================================\n--- c8c77f67ea85ee65a0f055f2cb76e6059eaa0776/merge-cache.c  (mode:100644)\n+++ uncommitted/merge-cache.c  (mode:100644)\n@@ -34,11 +34,11 @@\n \t}\n }\n \n-static int merge_entry(int pos, const char *path)\n+static int merge_entry(struct cache *cache, int pos, const char *path)\n {\n \tint found;\n \t\n-\tif (pos >= active_nr)\n+\tif (pos >= get_num_cache_entries(cache))\n \t\tdie(\"merge-cache: %s not in the cache\", path);\n \targuments[0] = pgm;\n \targuments[1] = \"\";\n@@ -52,7 +52,7 @@\n \tdo {\n \t\tstatic char hexbuf[4][60];\n \t\tstatic char ownbuf[4][60];\n-\t\tstruct cache_entry *ce = active_cache[pos];\n+\t\tstruct cache_entry *ce = get_cache_entry(cache, pos);\n \t\tint stage = ce_stage(ce);\n \n \t\tif (strcmp(ce->name, path))\n@@ -62,44 +62,45 @@\n \t\tsprintf(ownbuf[stage], \"%o\", ntohl(ce->ce_mode) & (~S_IFMT));\n \t\targuments[stage] = hexbuf[stage];\n \t\targuments[stage + 4] = ownbuf[stage];\n-\t} while (++pos < active_nr);\n+\t} while (++pos < get_num_cache_entries(cache));\n \tif (!found)\n \t\tdie(\"merge-cache: %s not in the cache\", path);\n \trun_program();\n \treturn found;\n }\n \n-static void merge_file(const char *path)\n+static void merge_file(struct cache *cache, const char *path)\n {\n-\tint pos = cache_name_pos(path, strlen(path));\n+\tint pos = cache_name_pos(cache, path, strlen(path));\n \n \t/*\n \t * If it already exists in the cache as stage0, it's\n \t * already merged and there is nothing to do.\n \t */\n \tif (pos < 0)\n-\t\tmerge_entry(-pos-1, path);\n+\t\tmerge_entry(cache, -pos-1, path);\n }\n \n-static void merge_all(void)\n+static void merge_all(struct cache *cache)\n {\n \tint i;\n-\tfor (i = 0; i < active_nr; i++) {\n-\t\tstruct cache_entry *ce = active_cache[i];\n+\tfor (i = 0; i < get_num_cache_entries(cache); i++) {\n+\t\tstruct cache_entry *ce = get_cache_entry(cache, i);\n \t\tif (!ce_stage(ce))\n \t\t\tcontinue;\n-\t\ti += merge_entry(i, ce->name)-1;\n+\t\ti += merge_entry(cache, i, ce->name)-1;\n \t}\n }\n \n int main(int argc, char **argv)\n {\n \tint i, force_file = 0;\n+\tstruct cache *cache;\n \n \tif (argc < 3)\n \t\tusage(\"merge-cache [-o] <merge-program> (-a | <filename>*)\");\n \n-\tread_cache();\n+\tcache = read_cache();\n \n \ti = 1;\n \tif (!strcmp(argv[1], \"-o\")) {\n@@ -115,12 +116,12 @@\n \t\t\t\tcontinue;\n \t\t\t}\n \t\t\tif (!strcmp(arg, \"-a\")) {\n-\t\t\t\tmerge_all();\n+\t\t\t\tmerge_all(cache);\n \t\t\t\tcontinue;\n \t\t\t}\n \t\t\tdie(\"merge-cache: unknown option %s\", arg);\n \t\t}\n-\t\tmerge_file(arg);\n+\t\tmerge_file(cache, arg);\n \t}\n \tif (err)\n \t\tdie(\"merge program failed\");\nIndex: read-cache.c\n===================================================================\n--- c8c77f67ea85ee65a0f055f2cb76e6059eaa0776/read-cache.c  (mode:100644)\n+++ uncommitted/read-cache.c  (mode:100644)\n@@ -6,10 +6,49 @@\n #include <stdarg.h>\n #include \"cache.h\"\n \n-struct cache_entry **active_cache = NULL;\n-unsigned int active_nr = 0, active_alloc = 0, active_cache_changed = 0;\n+/*\n+ * Basic data structures for the directory cache\n+ */\n+\n+#define CACHE_SIGNATURE 0x44495243\t/* \"DIRC\" */\n+struct cache_header {\n+\tunsigned int hdr_signature;\n+\tunsigned int hdr_version;\n+\tunsigned int hdr_entries;\n+};\n+\n+struct mmap_holder {\n+\tvoid * ptr;\n+\tsize_t size;\n+};\n+\n+struct cache {\n+\tstruct mmap_holder   map;\n+\tstruct cache_header *header;\n+\tstruct cache_entry **entries;\n+\tunsigned int num_entries;\n+\tunsigned int allocated_entries;\n+\tunsigned int active_cache_changed;\n+};\n+\n+struct cache * new_cache()\n+{\n+\tstruct cache *cache = xcalloc(1, sizeof(struct cache));\n+\n+\tcache->map.ptr = MAP_FAILED;\n+\n+\treturn cache;\n+}\n+\n+void free_cache(struct cache *cache)\n+{\n+\tif (cache->map.ptr != MAP_FAILED)\n+\t\tmunmap(cache->map.ptr, cache->map.size);\n+\n+\tfree(cache);\n+}\n \n-int cache_match_stat(struct cache_entry *ce, struct stat *st)\n+int ce_match_stat(struct cache_entry *ce, struct stat *st)\n {\n \tunsigned int changed = 0;\n \n@@ -75,15 +114,15 @@\n \treturn 0;\n }\n \n-int cache_name_pos(const char *name, int namelen)\n+int cache_name_pos(struct cache *cache, const char *name, int namelen)\n {\n \tint first, last;\n \n \tfirst = 0;\n-\tlast = active_nr;\n+\tlast = cache->num_entries;\n \twhile (last > first) {\n \t\tint next = (last + first) >> 1;\n-\t\tstruct cache_entry *ce = active_cache[next];\n+\t\tstruct cache_entry *ce = get_cache_entry(cache, next);\n \t\tint cmp = cache_name_compare(name, namelen, ce->name, htons(ce->ce_flags));\n \t\tif (!cmp)\n \t\t\treturn next;\n@@ -97,27 +136,27 @@\n }\n \n /* Remove entry, return true if there are more entries to go.. */\n-int remove_entry_at(int pos)\n+int remove_cache_entry_at(struct cache *cache, int pos)\n {\n-\tactive_cache_changed = 1;\n-\tactive_nr--;\n-\tif (pos >= active_nr)\n+\tcache->active_cache_changed = 1;\n+\tcache->num_entries--;\n+\tif (pos >= cache->num_entries)\n \t\treturn 0;\n-\tmemmove(active_cache + pos, active_cache + pos + 1, (active_nr - pos) * sizeof(struct cache_entry *));\n+\tmemmove(cache->entries + pos, cache->entries + pos + 1, (cache->num_entries - pos) * sizeof(struct cache_entry *));\n \treturn 1;\n }\n \n-int remove_file_from_cache(char *path)\n+int remove_file_from_cache(struct cache *cache, char *path)\n {\n-\tint pos = cache_name_pos(path, strlen(path));\n+\tint pos = cache_name_pos(cache, path, strlen(path));\n \tif (pos < 0)\n \t\tpos = -pos-1;\n-\twhile (pos < active_nr && !strcmp(active_cache[pos]->name, path))\n-\t\tremove_entry_at(pos);\n+\twhile (pos < get_num_cache_entries(cache) && !strcmp(get_cache_entry(cache, pos)->name, path))\n+\t\tremove_cache_entry_at(cache, pos);\n \treturn 0;\n }\n \n-int same_name(struct cache_entry *a, struct cache_entry *b)\n+int ce_same_name(struct cache_entry *a, struct cache_entry *b)\n {\n \tint len = ce_namelen(a);\n \treturn ce_namelen(b) == len && !memcmp(a->name, b->name, len);\n@@ -132,7 +171,8 @@\n  * from the cache so the caller should recompute the insert position.\n  * When this happens, we return non-zero.\n  */\n-static int check_file_directory_conflict(const struct cache_entry *ce,\n+static int check_file_directory_conflict(struct cache *cache,\n+\t\t\t\t\t const struct cache_entry *ce,\n \t\t\t\t\t int ok_to_replace)\n {\n \tint pos, replaced = 0;\n@@ -155,7 +195,7 @@\n \t\tif (!ep)\n \t\t\tbreak;\n \t\t*ep = 0;    /* first cut it at slash */\n-\t\tpos = cache_name_pos(pathbuf,\n+\t\tpos = cache_name_pos(cache, pathbuf,\n \t\t\t\t     htons(create_ce_flags(ep-cp, stage)));\n \t\tif (0 <= pos) {\n \t\t\t/* Our leading path component is registered as a file,\n@@ -167,7 +207,7 @@\n \t\t\t\treturn -1;\n \t\t\t}\n \t\t\tfprintf(stderr, \"removing file '%s' to replace it with a directory to create '%s'.\\n\", pathbuf, path);\n-\t\t\tremove_entry_at(pos);\n+\t\t\tremove_cache_entry_at(cache, pos);\n \t\t\treplaced = 1;\n \t\t}\n \t\t*ep = '/';  /* then restore it and go downwards */\n@@ -179,7 +219,7 @@\n \t * of it?  That is, are we creating a file where they already expect\n \t * a directory there?\n \t */\n-\tpos = cache_name_pos(path,\n+\tpos = cache_name_pos(cache, path,\n \t\t\t     htons(create_ce_flags(namelen, stage)));\n \n \t/* (0 <= pos) cannot happen because add_cache_entry()\n@@ -206,8 +246,8 @@\n \t * path of an existing entry anymore.\n \t */\n \n-\twhile (pos < active_nr) {\n-\t\tstruct cache_entry *other = active_cache[pos];\n+\twhile (pos < get_num_cache_entries(cache)) {\n+\t\tstruct cache_entry *other = get_cache_entry(cache, pos);\n \t\tif (strncmp(other->name, path, namelen))\n \t\t\tbreak; /* it is not our \"subdirectory\" anymore */\n \t\tif ((ce_stage(other) == stage) &&\n@@ -215,7 +255,7 @@\n \t\t\tif (!ok_to_replace)\n \t\t\t\treturn -1;\n \t\t\tfprintf(stderr, \"removing file '%s' under '%s' to be replaced with a file\\n\", other->name, path);\n-\t\t\tremove_entry_at(pos);\n+\t\t\tremove_cache_entry_at(cache, pos);\n \t\t\treplaced = 1;\n \t\t\tcontinue; /* cycle without updating pos */\n \t\t}\n@@ -224,17 +264,35 @@\n \treturn replaced;\n }\n \n-int add_cache_entry(struct cache_entry *ce, int option)\n+void set_cache_entry(struct cache *cache, struct cache_entry *ce, int pos)\n+{\n+\tcache->active_cache_changed = 1;\n+\tcache->entries[pos] = ce;\n+}\n+\n+int get_num_cache_entries(struct cache *cache)\n+{\n+\treturn cache->num_entries;\n+}\n+\n+struct cache_entry *get_cache_entry(struct cache *cache, int pos)\n+{\n+ \t/* You can NOT just free cache->entries[pos] here, since it\n+  \t * might not be necessarily malloc()ed but can also come\n+  \t * from mmap(). */\n+\treturn cache->entries[pos];\n+}\n+\n+int add_cache_entry(struct cache *cache, struct cache_entry *ce, int option)\n {\n \tint pos;\n \tint ok_to_add = option & ADD_CACHE_OK_TO_ADD;\n \tint ok_to_replace = option & ADD_CACHE_OK_TO_REPLACE;\n-\tpos = cache_name_pos(ce->name, htons(ce->ce_flags));\n+\tpos = cache_name_pos(cache, ce->name, htons(ce->ce_flags));\n \n \t/* existing match? Just replace it */\n \tif (pos >= 0) {\n-\t\tactive_cache_changed = 1;\n-\t\tactive_cache[pos] = ce;\n+\t\tset_cache_entry(cache, ce, pos);\n \t\treturn 0;\n \t}\n \tpos = -pos-1;\n@@ -243,10 +301,10 @@\n \t * Inserting a merged entry (\"stage 0\") into the index\n \t * will always replace all non-merged entries..\n \t */\n-\tif (pos < active_nr && ce_stage(ce) == 0) {\n-\t\twhile (same_name(active_cache[pos], ce)) {\n+\tif (pos < get_num_cache_entries(cache) && ce_stage(ce) == 0) {\n+\t\twhile (ce_same_name(get_cache_entry(cache, pos), ce)) {\n \t\t\tok_to_add = 1;\n-\t\t\tif (!remove_entry_at(pos))\n+\t\t\tif (!remove_cache_entry_at(cache, pos))\n \t\t\t\tbreak;\n \t\t}\n \t}\n@@ -254,25 +312,24 @@\n \tif (!ok_to_add)\n \t\treturn -1;\n \n-\tif (check_file_directory_conflict(ce, ok_to_replace)) {\n+\tif (check_file_directory_conflict(cache, ce, ok_to_replace)) {\n \t\tif (!ok_to_replace)\n \t\t\treturn -1;\n-\t\tpos = cache_name_pos(ce->name, htons(ce->ce_flags));\n+\t\tpos = cache_name_pos(cache, ce->name, htons(ce->ce_flags));\n \t\tpos = -pos-1;\n \t}\n \n \t/* Make sure the array is big enough .. */\n-\tif (active_nr == active_alloc) {\n-\t\tactive_alloc = alloc_nr(active_alloc);\n-\t\tactive_cache = xrealloc(active_cache, active_alloc * sizeof(struct cache_entry *));\n+\tif (cache->num_entries == cache->allocated_entries) {\n+\t\tcache->allocated_entries = alloc_nr(cache->allocated_entries);\n+\t\tcache->entries = xrealloc(cache->entries, cache->allocated_entries * sizeof(struct cache_entry *));\n \t}\n \n \t/* Add it in.. */\n-\tactive_nr++;\n-\tif (active_nr > pos)\n-\t\tmemmove(active_cache + pos + 1, active_cache + pos, (active_nr - pos - 1) * sizeof(ce));\n-\tactive_cache[pos] = ce;\n-\tactive_cache_changed = 1;\n+\tcache->num_entries++;\n+\tif (cache->num_entries > pos)\n+\t\tmemmove(cache->entries + pos + 1, cache->entries + pos, (cache->num_entries - pos - 1) * sizeof(ce));\n+\tset_cache_entry(cache, ce, pos);\n \treturn 0;\n }\n \n@@ -293,54 +350,56 @@\n \treturn 0;\n }\n \n-int read_cache(void)\n+struct cache *read_cache(void)\n {\n \tint fd, i;\n \tstruct stat st;\n-\tunsigned long size, offset;\n-\tvoid *map;\n-\tstruct cache_header *hdr;\n-\n-\terrno = EBUSY;\n-\tif (active_cache)\n-\t\treturn error(\"more than one cachefile\");\n+\tunsigned long offset;\n+\tstruct cache *cache = new_cache();\n+\n \terrno = ENOENT;\n \tfd = open(get_index_file(), O_RDONLY);\n-\tif (fd < 0)\n-\t\treturn (errno == ENOENT) ? 0 : error(\"open failed\");\n+\tif (fd < 0) {\n+\t\tif (errno == ENOENT)\n+\t\t\treturn cache;\n+\t\telse {\n+\t\t\tfree_cache(cache);\n+\t\t\treturn NULL;\n+\t\t}\n+\t}\n \n-\tsize = 0; // avoid gcc warning\n-\tmap = (void *)-1;\n \tif (!fstat(fd, &st)) {\n-\t\tsize = st.st_size;\n+\t\tcache->map.size = st.st_size;\n \t\terrno = EINVAL;\n-\t\tif (size >= sizeof(struct cache_header) + 20)\n-\t\t\tmap = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);\n+\t\tif (cache->map.size >= sizeof(struct cache_header) + 20)\n+\t\t\tcache->map.ptr = mmap(NULL, cache->map.size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);\n \t}\n \tclose(fd);\n-\tif (-1 == (int)(long)map)\n-\t\treturn error(\"mmap failed\");\n+\tif (MAP_FAILED == cache->map.ptr) {\n+\t\terror(\"mmap failed\");\n+\t\tfree_cache(cache);\n+\t\treturn NULL;\n+\t}\n \n-\thdr = map;\n-\tif (verify_hdr(hdr, size) < 0)\n-\t\tgoto unmap;\n-\n-\tactive_nr = ntohl(hdr->hdr_entries);\n-\tactive_alloc = alloc_nr(active_nr);\n-\tactive_cache = calloc(active_alloc, sizeof(struct cache_entry *));\n-\n-\toffset = sizeof(*hdr);\n-\tfor (i = 0; i < active_nr; i++) {\n-\t\tstruct cache_entry *ce = map + offset;\n-\t\toffset = offset + ce_size(ce);\n-\t\tactive_cache[i] = ce;\n+\tcache->header = cache->map.ptr;\n+\tif (verify_hdr(cache->header, cache->map.size) < 0) {\n+\t\tfree_cache(cache);\n+\t\terrno = EINVAL;\n+\t\terror(\"verify header failed\");\n+\t\treturn NULL;\n \t}\n-\treturn active_nr;\n \n-unmap:\n-\tmunmap(map, size);\n-\terrno = EINVAL;\n-\treturn error(\"verify header failed\");\n+\tcache->num_entries = ntohl(cache->header->hdr_entries);\n+\tcache->allocated_entries = alloc_nr(cache->num_entries);\n+\tcache->entries = xcalloc(cache->allocated_entries, sizeof(struct cache_entry *));\n+\n+\toffset = sizeof(*cache->header);\n+\tfor (i = 0; i < cache->num_entries; i++) {\n+\t\tstruct cache_entry *ce = cache->map.ptr + offset;\n+\t\toffset = offset + ce_size(ce);\n+\t\tcache->entries[i] = ce;\n+\t}\n+\treturn cache;\n }\n \n #define WRITE_BUFFER_SIZE 8192\n@@ -386,7 +445,7 @@\n \treturn 0;\n }\n \n-int write_cache(int newfd, struct cache_entry **cache, int entries)\n+int write_cache(struct cache *cache, int newfd)\n {\n \tSHA_CTX c;\n \tstruct cache_header hdr;\n@@ -394,14 +453,14 @@\n \n \thdr.hdr_signature = htonl(CACHE_SIGNATURE);\n \thdr.hdr_version = htonl(2);\n-\thdr.hdr_entries = htonl(entries);\n+\thdr.hdr_entries = htonl(get_num_cache_entries(cache));\n \n \tSHA1_Init(&c);\n \tif (ce_write(&c, newfd, &hdr, sizeof(hdr)) < 0)\n \t\treturn -1;\n \n-\tfor (i = 0; i < entries; i++) {\n-\t\tstruct cache_entry *ce = cache[i];\n+\tfor (i = 0; i < get_num_cache_entries(cache); i++) {\n+\t\tstruct cache_entry *ce = get_cache_entry(cache, i);\n \t\tif (ce_write(&c, newfd, ce, ce_size(ce)) < 0)\n \t\t\treturn -1;\n \t}\nIndex: read-tree.c\n===================================================================\n--- c8c77f67ea85ee65a0f055f2cb76e6059eaa0776/read-tree.c  (mode:100644)\n+++ uncommitted/read-tree.c  (mode:100644)\n@@ -7,7 +7,7 @@\n \n static int stage = 0;\n \n-static int unpack_tree(unsigned char *sha1)\n+static int unpack_tree(struct cache *cache, unsigned char *sha1)\n {\n \tvoid *buffer;\n \tunsigned long size;\n@@ -16,7 +16,7 @@\n \tbuffer = read_object_with_reference(sha1, \"tree\", &size, 0);\n \tif (!buffer)\n \t\treturn -1;\n-\tret = read_tree(buffer, size, stage);\n+\tret = read_tree(cache, buffer, size, stage);\n \tfree(buffer);\n \treturn ret;\n }\n@@ -93,26 +93,30 @@\n \treturn NULL;\n }\n \n-static void trivially_merge_cache(struct cache_entry **src, int nr)\n+/* rather than doing the 'right' thing of deleting entries as we merge,\n+ * walk dst through the cache, overwriting entries as we go and at the\n+ * end truncate the size of the cache */\n+static void trivially_merge_cache(struct cache *cache)\n {\n \tstatic struct cache_entry null_entry;\n-\tstruct cache_entry **dst = src;\n \tstruct cache_entry *old = &null_entry;\n+\tint src = 0, dst = 0, nr = get_num_cache_entries(cache);\n \n-\twhile (nr) {\n+\twhile (src < nr) {\n \t\tstruct cache_entry *ce, *result;\n \n-\t\tce = src[0];\n+\t\tce = get_cache_entry(cache, src);\n \n \t\t/* We throw away original cache entries except for the stat information */\n \t\tif (!ce_stage(ce)) {\n \t\t\told = ce;\n \t\t\tsrc++;\n-\t\t\tnr--;\n-\t\t\tactive_nr--;\n \t\t\tcontinue;\n \t\t}\n-\t\tif (nr > 2 && (result = merge_entries(ce, src[1], src[2])) != NULL) {\n+\t\tif ((src < (nr - 2)) &&\n+\t\t    (result = merge_entries(ce,\n+\t\t\t\t\t    get_cache_entry(cache, src + 1),\n+\t\t\t\t\t    get_cache_entry(cache, src + 2))) != NULL) {\n \t\t\t/*\n \t\t\t * See if we can re-use the old CE directly?\n \t\t\t * That way we get the uptodate stat info.\n@@ -122,40 +126,46 @@\n \t\t\tce = result;\n \t\t\tce->ce_flags &= ~htons(CE_STAGEMASK);\n \t\t\tsrc += 2;\n-\t\t\tnr -= 2;\n-\t\t\tactive_nr -= 2;\n \t\t}\n-\t\t*dst++ = ce;\n+\t\tset_cache_entry(cache, ce, dst);\n+\t\tdst++;\n \t\tsrc++;\n+\t}\n+\t/* this could be replaced by a truncate api */\n+\twhile (nr > dst) {\n \t\tnr--;\n+\t\tremove_cache_entry_at(cache, nr);\n \t}\n }\n \n-static void merge_stat_info(struct cache_entry **src, int nr)\n+static void merge_stat_info(struct cache *cache)\n {\n \tstatic struct cache_entry null_entry;\n-\tstruct cache_entry **dst = src;\n \tstruct cache_entry *old = &null_entry;\n+\tint src = 0, dst = 0, nr = get_num_cache_entries(cache);\n \n-\twhile (nr) {\n+\twhile (src < nr) {\n \t\tstruct cache_entry *ce;\n \n-\t\tce = src[0];\n+\t\tce = get_cache_entry(cache, src);\n \n \t\t/* We throw away original cache entries except for the stat information */\n \t\tif (!ce_stage(ce)) {\n \t\t\told = ce;\n \t\t\tsrc++;\n-\t\t\tnr--;\n-\t\t\tactive_nr--;\n \t\t\tcontinue;\n \t\t}\n \t\tif (path_matches(ce, old) && same(ce, old))\n \t\t\t*ce = *old;\n \t\tce->ce_flags &= ~htons(CE_STAGEMASK);\n-\t\t*dst++ = ce;\n+\t\tset_cache_entry(cache, ce, dst);\n+\t\tdst++;\n \t\tsrc++;\n+\t}\n+\t/* this could be replaced by a truncate api */\n+\twhile (nr > dst) {\n \t\tnr--;\n+\t\tremove_cache_entry_at(cache, nr);\n \t}\n }\n \n@@ -167,6 +177,7 @@\n \tunsigned char sha1[20];\n \tstatic char lockfile[MAXPATHLEN+1];\n \tconst char *indexfile = get_index_file();\n+\tstruct cache *cache = NULL;\n \n \tsnprintf(lockfile, sizeof(lockfile), \"%s.lock\", indexfile);\n \n@@ -185,9 +196,9 @@\n \t\t\tint i;\n \t\t\tif (stage)\n \t\t\t\tdie(\"-m needs to come first\");\n-\t\t\tread_cache();\n-\t\t\tfor (i = 0; i < active_nr; i++) {\n-\t\t\t\tif (ce_stage(active_cache[i]))\n+\t\t\tcache = read_cache();\n+\t\t\tfor (i = 0; i < get_num_cache_entries(cache); i++) {\n+\t\t\t\tif (ce_stage(get_cache_entry(cache, i)))\n \t\t\t\t\tdie(\"you need to resolve your current index first\");\n \t\t\t}\n \t\t\tstage = 1;\n@@ -198,23 +209,25 @@\n \t\t\tusage(read_tree_usage);\n \t\tif (stage > 3)\n \t\t\tusage(read_tree_usage);\n-\t\tif (unpack_tree(sha1) < 0)\n+\t\tif (!cache)\n+\t\t\tcache = new_cache();\n+\t\tif (unpack_tree(cache, sha1) < 0)\n \t\t\tdie(\"failed to unpack tree object %s\", arg);\n \t\tstage++;\n \t}\n \tif (merge) {\n \t\tswitch (stage) {\n \t\tcase 4:\t/* Three-way merge */\n-\t\t\ttrivially_merge_cache(active_cache, active_nr);\n+\t\t\ttrivially_merge_cache(cache);\n \t\t\tbreak;\n \t\tcase 2:\t/* Just read a tree, merge with old cache contents */\n-\t\t\tmerge_stat_info(active_cache, active_nr);\n+\t\t\tmerge_stat_info(cache);\n \t\t\tbreak;\n \t\tdefault:\n \t\t\tdie(\"just how do you expect me to merge %d trees?\", stage-1);\n \t\t}\n \t}\n-\tif (write_cache(newfd, active_cache, active_nr) || rename(lockfile, indexfile))\n+\tif (write_cache(cache, newfd) || rename(lockfile, indexfile))\n \t\tdie(\"unable to write new index file\");\n \tlockfile_name = NULL;\n \treturn 0;\nIndex: sha1_file.c\n===================================================================\n--- c8c77f67ea85ee65a0f055f2cb76e6059eaa0776/sha1_file.c  (mode:100644)\n+++ uncommitted/sha1_file.c  (mode:100644)\n@@ -302,7 +302,7 @@\n \t}\n \tmap = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);\n \tclose(fd);\n-\tif (-1 == (int)(long)map)\n+\tif (MAP_FAILED == map)\n \t\treturn NULL;\n \t*size = st.st_size;\n \treturn map;\n@@ -587,7 +587,7 @@\n \tif (size)\n \t\tbuf = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);\n \tclose(fd);\n-\tif ((int)(long)buf == -1)\n+\tif (buf == MAP_FAILED)\n \t\treturn -1;\n \n \tret = write_sha1_file(buf, size, \"blob\", sha1);\nIndex: tree.c\n===================================================================\n--- c8c77f67ea85ee65a0f055f2cb76e6059eaa0776/tree.c  (mode:100644)\n+++ uncommitted/tree.c  (mode:100644)\n@@ -5,7 +5,8 @@\n \n const char *tree_type = \"tree\";\n \n-static int read_one_entry(unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage)\n+static int read_one_entry(struct cache *cache, unsigned char *sha1, const char *base,\n+\t\t          int baselen, const char *pathname, unsigned mode, int stage)\n {\n \tint len = strlen(pathname);\n \tunsigned int size = cache_entry_size(baselen + len);\n@@ -18,10 +19,10 @@\n \tmemcpy(ce->name, base, baselen);\n \tmemcpy(ce->name + baselen, pathname, len+1);\n \tmemcpy(ce->sha1, sha1, 20);\n-\treturn add_cache_entry(ce, ADD_CACHE_OK_TO_ADD);\n+\treturn add_cache_entry(cache, ce, ADD_CACHE_OK_TO_ADD);\n }\n \n-static int read_tree_recursive(void *buffer, unsigned long size,\n+static int read_tree_recursive(struct cache* cache, void *buffer, unsigned long size,\n \t\t\t       const char *base, int baselen, int stage)\n {\n \twhile (size) {\n@@ -53,7 +54,7 @@\n \t\t\tmemcpy(newbase, base, baselen);\n \t\t\tmemcpy(newbase + baselen, path, pathlen);\n \t\t\tnewbase[baselen + pathlen] = '/';\n-\t\t\tretval = read_tree_recursive(eltbuf, eltsize,\n+\t\t\tretval = read_tree_recursive(cache, eltbuf, eltsize,\n \t\t\t\t\t\t     newbase,\n \t\t\t\t\t\t     baselen + pathlen + 1, stage);\n \t\t\tfree(eltbuf);\n@@ -62,15 +63,15 @@\n \t\t\t\treturn -1;\n \t\t\tcontinue;\n \t\t}\n-\t\tif (read_one_entry(sha1, base, baselen, path, mode, stage) < 0)\n+\t\tif (read_one_entry(cache, sha1, base, baselen, path, mode, stage) < 0)\n \t\t\treturn -1;\n \t}\n \treturn 0;\n }\n \n-int read_tree(void *buffer, unsigned long size, int stage)\n+int read_tree(struct cache *cache, void *buffer, unsigned long size, int stage)\n {\n-\treturn read_tree_recursive(buffer, size, \"\", 0, stage);\n+\treturn read_tree_recursive(cache, buffer, size, \"\", 0, stage);\n }\n \n struct tree *lookup_tree(unsigned char *sha1)\nIndex: update-cache.c\n===================================================================\n--- c8c77f67ea85ee65a0f055f2cb76e6059eaa0776/update-cache.c  (mode:100644)\n+++ uncommitted/update-cache.c  (mode:100644)\n@@ -51,7 +51,7 @@\n \tce->ce_size = htonl(st->st_size);\n }\n \n-static int add_file_to_cache(char *path)\n+static int add_file_to_cache(struct cache *cache, char *path)\n {\n \tint size, namelen, option, status;\n \tstruct cache_entry *ce;\n@@ -71,7 +71,7 @@\n \t\t */\n \t\tif (status == 0 || (errno == ENOENT || errno == ENOTDIR)) {\n \t\t\tif (allow_remove)\n-\t\t\t\treturn remove_file_from_cache(path);\n+\t\t\t\treturn remove_file_from_cache(cache, path);\n \t\t}\n \t\treturn error(\"open(\\\"%s\\\"): %s\", path, strerror(errno));\n \t}\n@@ -106,7 +106,7 @@\n \t}\n \toption = allow_add ? ADD_CACHE_OK_TO_ADD : 0;\n \toption |= allow_replace ? ADD_CACHE_OK_TO_REPLACE : 0;\n-\treturn add_cache_entry(ce, option);\n+\treturn add_cache_entry(cache, ce, option);\n }\n \n static int match_data(int fd, void *buffer, unsigned long size)\n@@ -191,7 +191,7 @@\n \tif (lstat(ce->name, &st) < 0)\n \t\treturn ERR_PTR(-errno);\n \n-\tchanged = cache_match_stat(ce, &st);\n+\tchanged = ce_match_stat(ce, &st);\n \tif (!changed)\n \t\treturn ce;\n \n@@ -222,19 +222,19 @@\n \treturn updated;\n }\n \n-static int refresh_cache(void)\n+static int refresh_cache(struct cache *cache)\n {\n \tint i;\n \tint has_errors = 0;\n \n-\tfor (i = 0; i < active_nr; i++) {\n+\tfor (i = 0; i < get_num_cache_entries(cache); i++) {\n \t\tstruct cache_entry *ce, *new;\n-\t\tce = active_cache[i];\n+\t\tce = get_cache_entry(cache, i);\n \t\tif (ce_stage(ce)) {\n \t\t\tprintf(\"%s: needs merge\\n\", ce->name);\n \t\t\thas_errors = 1;\n-\t\t\twhile ((i < active_nr) &&\n-\t\t\t       ! strcmp(active_cache[i]->name, ce->name))\n+\t\t\twhile ((i < get_num_cache_entries(cache)) &&\n+\t\t\t       ! strcmp(get_cache_entry(cache, i)->name, ce->name))\n \t\t\t\ti++;\n \t\t\ti--;\n \t\t\tcontinue;\n@@ -248,11 +248,7 @@\n \t\t\t}\n \t\t\tcontinue;\n \t\t}\n-\t\tactive_cache_changed = 1;\n-\t\t/* You can NOT just free active_cache[i] here, since it\n-\t\t * might not be necessarily malloc()ed but can also come\n-\t\t * from mmap(). */\n-\t\tactive_cache[i] = new;\n+\t\tset_cache_entry(cache, new, i);\n \t}\n \treturn has_errors;\n }\n@@ -285,7 +281,7 @@\n \t}\n }\n \n-static int add_cacheinfo(char *arg1, char *arg2, char *arg3)\n+static int add_cacheinfo(struct cache *cache, char *arg1, char *arg2, char *arg3)\n {\n \tint size, len, option;\n \tunsigned int mode;\n@@ -310,7 +306,7 @@\n \tce->ce_mode = create_ce_mode(mode);\n \toption = allow_add ? ADD_CACHE_OK_TO_ADD : 0;\n \toption |= allow_replace ? ADD_CACHE_OK_TO_REPLACE : 0;\n-\treturn add_cache_entry(ce, option);\n+\treturn add_cache_entry(cache, ce, option);\n }\n \n static const char *lockfile_name = NULL;\n@@ -328,10 +324,11 @@\n \n int main(int argc, char **argv)\n {\n-\tint i, newfd, entries, has_errors = 0;\n+\tint i, newfd, has_errors = 0;\n \tint allow_options = 1;\n \tstatic char lockfile[MAXPATHLEN+1];\n \tconst char *indexfile = get_index_file();\n+\tstruct cache *cache = NULL;\n \n \tsnprintf(lockfile, sizeof(lockfile), \"%s.lock\", indexfile);\n \n@@ -343,8 +340,8 @@\n \tatexit(remove_lock_file);\n \tlockfile_name = lockfile;\n \n-\tentries = read_cache();\n-\tif (entries < 0)\n+\tcache = read_cache();\n+\tif (!cache)\n \t\tdie(\"cache corrupted\");\n \n \tfor (i = 1 ; i < argc; i++) {\n@@ -368,13 +365,13 @@\n \t\t\t\tcontinue;\n \t\t\t}\n \t\t\tif (!strcmp(path, \"--refresh\")) {\n-\t\t\t\thas_errors |= refresh_cache();\n+\t\t\t\thas_errors |= refresh_cache(cache);\n \t\t\t\tcontinue;\n \t\t\t}\n \t\t\tif (!strcmp(path, \"--cacheinfo\")) {\n \t\t\t\tif (i+3 >= argc)\n \t\t\t\t\tdie(\"update-cache: --cacheinfo <mode> <sha1> <path>\");\n-\t\t\t\tif (add_cacheinfo(argv[i+1], argv[i+2], argv[i+3]))\n+\t\t\t\tif (add_cacheinfo(cache, argv[i+1], argv[i+2], argv[i+3]))\n \t\t\t\t\tdie(\"update-cache: --cacheinfo cannot add %s\", argv[i+3]);\n \t\t\t\ti += 3;\n \t\t\t\tcontinue;\n@@ -382,7 +379,7 @@\n \t\t\tif (!strcmp(path, \"--force-remove\")) {\n \t\t\t\tif (argc <= i + 1)\n \t\t\t\t\tdie(\"update-cache: --force-remove <path>\");\n-\t\t\t\tif (remove_file_from_cache(argv[i+1]))\n+\t\t\t\tif (remove_file_from_cache(cache, argv[i+1]))\n \t\t\t\t\tdie(\"update-cache: --force-remove cannot remove %s\", argv[i+1]);\n \t\t\t\ti++;\n \t\t\t\tcontinue;\n@@ -398,10 +395,10 @@\n \t\t\tfprintf(stderr, \"Ignoring path %s\\n\", argv[i]);\n \t\t\tcontinue;\n \t\t}\n-\t\tif (add_file_to_cache(path))\n+\t\tif (add_file_to_cache(cache, path))\n \t\t\tdie(\"Unable to add %s to database\", path);\n \t}\n-\tif (write_cache(newfd, active_cache, active_nr) || rename(lockfile, indexfile))\n+\tif (write_cache(cache, newfd) || rename(lockfile, indexfile))\n \t\tdie(\"Unable to write new cachefile\");\n \n \tlockfile_name = NULL;\nIndex: write-tree.c\n===================================================================\n--- c8c77f67ea85ee65a0f055f2cb76e6059eaa0776/write-tree.c  (mode:100644)\n+++ uncommitted/write-tree.c  (mode:100644)\n@@ -17,7 +17,7 @@\n \treturn ret;\n }\n \n-static int write_tree(struct cache_entry **cachep, int maxentries, const char *base, int baselen, unsigned char *returnsha1)\n+static int write_tree(struct cache *cache, int start_pos, const char *base, int baselen, unsigned char *returnsha1)\n {\n \tunsigned char subdir_sha1[20];\n \tunsigned long size, offset;\n@@ -30,8 +30,8 @@\n \toffset = 0;\n \n \tnr = 0;\n-\twhile (nr < maxentries) {\n-\t\tstruct cache_entry *ce = cachep[nr];\n+\twhile ((start_pos + nr) < get_num_cache_entries(cache)) {\n+\t\tstruct cache_entry *ce = get_cache_entry(cache, start_pos + nr);\n \t\tconst char *pathname = ce->name, *filename, *dirname;\n \t\tint pathlen = ce_namelen(ce), entrylen;\n \t\tunsigned char *sha1;\n@@ -41,16 +41,13 @@\n \t\tif (baselen >= pathlen || memcmp(base, pathname, baselen))\n \t\t\tbreak;\n \n-\t\tsha1 = ce->sha1;\n-\t\tmode = ntohl(ce->ce_mode);\n-\n \t\t/* Do we have _further_ subdirectories? */\n \t\tfilename = pathname + baselen;\n \t\tdirname = strchr(filename, '/');\n \t\tif (dirname) {\n \t\t\tint subdir_written;\n \n-\t\t\tsubdir_written = write_tree(cachep + nr, maxentries - nr, pathname, dirname-pathname+1, subdir_sha1);\n+\t\t\tsubdir_written = write_tree(cache, start_pos + nr, pathname, dirname-pathname+1, subdir_sha1);\n \t\t\tnr += subdir_written;\n \n \t\t\t/* Now we need to write out the directory entry into this tree.. */\n@@ -60,6 +57,9 @@\n \t\t\t/* ..but the directory entry doesn't count towards the total count */\n \t\t\tnr--;\n \t\t\tsha1 = subdir_sha1;\n+\t\t} else {\n+\t\t\tsha1 = ce->sha1;\n+\t\t\tmode = ntohl(ce->ce_mode);\n \t\t}\n \n \t\tif (check_valid_sha1(sha1) < 0)\n@@ -85,16 +85,19 @@\n int main(int argc, char **argv)\n {\n \tint i, funny;\n-\tint entries = read_cache();\n+\tstruct cache *cache = read_cache();\n+\tint entries;\n \tunsigned char sha1[20];\n \n-\tif (entries < 0)\n+\tif (!cache)\n \t\tdie(\"write-tree: error reading cache\");\n \n+\tentries = get_num_cache_entries(cache);\n+\n \t/* Verify that the tree is merged */\n \tfunny = 0;\n \tfor (i = 0; i < entries; i++) {\n-\t\tstruct cache_entry *ce = active_cache[i];\n+\t\tstruct cache_entry *ce = get_cache_entry(cache, i);\n \t\tif (ntohs(ce->ce_flags) & ~CE_NAMEMASK) {\n \t\t\tif (10 < ++funny) {\n \t\t\t\tfprintf(stderr, \"...\\n\");\n@@ -116,8 +119,8 @@\n \t\t * the cache is sorted.  Also path can appear only once,\n \t\t * which means conflicting one would immediately follow.\n \t\t */\n-\t\tconst char *this_name = active_cache[i]->name;\n-\t\tconst char *next_name = active_cache[i+1]->name;\n+\t\tconst char *this_name = get_cache_entry(cache, i)->name;\n+\t\tconst char *next_name = get_cache_entry(cache, i+1)->name;\n \t\tint this_len = strlen(this_name);\n \t\tif (this_len < strlen(next_name) &&\n \t\t    strncmp(this_name, next_name, this_len) == 0 &&\n@@ -134,7 +137,7 @@\n \t\tdie(\"write-tree: not able to write tree\");\n \n \t/* Ok, write it out */\n-\tif (write_tree(active_cache, entries, \"\", 0, sha1) != entries)\n+\tif (write_tree(cache, 0, \"\", 0, sha1) != entries)\n \t\tdie(\"write-tree: internal error\");\n \tprintf(\"%s\\n\", sha1_to_hex(sha1));\n \treturn 0;\n"},{"id":"3352","messageId":"20050515114847.GD13024@pasky.ji.cz","threadId":"626","inReplyTo":"Pine.LNX.4.44.0505141851340.2136-200000@bellevue.puremagic.com","subject":"Re: Darcs-git: a few notes for Git hackers","fromName":"Petr Baudis","fromEmail":"pasky@ucw.cz","sentAt":"2005-05-15T11:48:47Z","receivedAt":"2005-05-15T11:48:47Z","isPatch":false,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Sun, May 15, 2005 at 04:04:25AM CEST, I got a letter\nwhere Brad Roberts <braddr@puremagic.com> told me that...\n> > I wasn't able to finish redoing these against linus tip, but I got most of\n> > it done (patches 1-14 of the original 19):\n> >\n> >   http://gameboy2.puremagic.com:8090/\n> >   rsync://gameboy2.puremagic.com/git/\n> >\n> > The second, third, and forth to last changes need a careful review,\n> > they're direct applications of the original patches which were lightly\n> > tested during the first round and nothing other than compile tested in\n> > this round.\n> >\n> > I suspect the remaining parts of the original patch series will go in\n> > fairly smoothly.  If no one gets to them before tonight I'll finish\n> > it up after work.\n> >\n> > Later,\n> > Brad\n> \n> I've completed the re-merge, and moved to tip of git-pb.git rather than\n> tip of git.git.  Unfortunatly that merge was also somewhat intrusive and\n> my individual diffs along the way are somewhat useless now.  The entire\n> history is available about the above locations still.  Attached is the\n> full diff vs git-pb @ 902b92e00e491a60d55c4b2bce122903b8347f34.\n\nI've merged some of the minor stuff for now.\n\n> 2) Should the index changing areas be constructing a new index instead of\n> shuffling bits within the current index?\n\nWhen I have a big cache (the only time it matters), I do usually only\nrelatively small changes to it, so...\n\n> 3) The vocabulary and code is inconsistent between cache and index.\n\nYes...\n\n> 4) read-cache.c does much more than reading.\n\nand yes. And cache.h is full of crap. Perhaps we could move read-cache.c\nto cache.c?\n\n\nI'd imagine the plan of attack to continue by changing active_cache to\nbe struct cache, then making it local.\n\n-- \n\t\t\t\tPetr \"Pasky\" Baudis\nStuff: http://pasky.or.cz/\nC++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor\n"},{"id":"3376","messageId":"Pine.LNX.4.44.0505151204230.2136-100000@bellevue.puremagic.com","threadId":"626","inReplyTo":"20050515114847.GD13024@pasky.ji.cz","subject":"Re: Darcs-git: a few notes for Git hackers","fromName":"Brad Roberts","fromEmail":"braddr@puremagic.com","sentAt":"2005-05-15T19:06:27Z","receivedAt":"2005-05-15T19:06:27Z","isPatch":false,"sender":{"key":"braddr@puremagic.com","avatar":null},"body":"> Date: Sun, 15 May 2005 13:48:47 +0200\n> From: Petr Baudis <pasky@ucw.cz>\n> To: Brad Roberts <braddr@puremagic.com>\n> Cc: Juliusz Chroboczek <Juliusz.Chroboczek@pps.jussieu.fr>,\n>      git@vger.kernel.org\n> Subject: Re: Darcs-git: a few notes for Git hackers\n>\n> Dear diary, on Sun, May 15, 2005 at 04:04:25AM CEST, I got a letter\n> where Brad Roberts <braddr@puremagic.com> told me that...\n> > > I wasn't able to finish redoing these against linus tip, but I got most of\n> > > it done (patches 1-14 of the original 19):\n> > >\n> > >   http://gameboy2.puremagic.com:8090/\n> > >   rsync://gameboy2.puremagic.com/git/\n> > >\n> > > The second, third, and forth to last changes need a careful review,\n> > > they're direct applications of the original patches which were lightly\n> > > tested during the first round and nothing other than compile tested in\n> > > this round.\n> > >\n> > > I suspect the remaining parts of the original patch series will go in\n> > > fairly smoothly.  If no one gets to them before tonight I'll finish\n> > > it up after work.\n> > >\n> > > Later,\n> > > Brad\n> >\n> > I've completed the re-merge, and moved to tip of git-pb.git rather than\n> > tip of git.git.  Unfortunatly that merge was also somewhat intrusive and\n> > my individual diffs along the way are somewhat useless now.  The entire\n> > history is available about the above locations still.  Attached is the\n> > full diff vs git-pb @ 902b92e00e491a60d55c4b2bce122903b8347f34.\n>\n> I've merged some of the minor stuff for now.\n\nCool, though there appears to have been some objections. :)\n\n> > 2) Should the index changing areas be constructing a new index instead of\n> > shuffling bits within the current index?\n>\n> When I have a big cache (the only time it matters), I do usually only\n> relatively small changes to it, so...\n\nThe entire index is bit shuffled around even if nothing changed.  At least\ntoday, size and amount changed doesn't matter.\n\n> > 3) The vocabulary and code is inconsistent between cache and index.\n>\n> Yes...\n>\n> > 4) read-cache.c does much more than reading.\n>\n> and yes. And cache.h is full of crap. Perhaps we could move read-cache.c\n> to cache.c?\n\nAt least parts of it, probably yes.\n\n> I'd imagine the plan of attack to continue by changing active_cache to\n> be struct cache, then making it local.\n\nWhich is what the rest of that patch does.\n\nThanks for looking at this.\n\nLater,\nBrad\n\n"},{"id":"3377","messageId":"7vfywothpp.fsf@assigned-by-dhcp.cox.net","threadId":"626","inReplyTo":"Pine.LNX.4.44.0505151204230.2136-100000@bellevue.puremagic.com","subject":"Re: Darcs-git: a few notes for Git hackers","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-05-15T19:25:06Z","receivedAt":"2005-05-15T19:25:06Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":">>>>> \"BR\" == Brad Roberts <braddr@puremagic.com> writes:\n\n>> I've merged some of the minor stuff for now.\n\nBR> Cool, though there appears to have been some objections. :)\n\nI do not have any problem with what the _patch_ does at all.  I\nhad more trouble in the process of how the patch appeared in\ngit-pb tree, and I still do.\n\nPlease consider the revert request retracted.  Request to\nforewarn people in the mailing list still stands.\n\n"},{"id":"3379","messageId":"20050515194803.GI13024@pasky.ji.cz","threadId":"626","inReplyTo":"7vfywothpp.fsf@assigned-by-dhcp.cox.net","subject":"Re: Darcs-git: a few notes for Git hackers","fromName":"Petr Baudis","fromEmail":"pasky@ucw.cz","sentAt":"2005-05-15T19:48:03Z","receivedAt":"2005-05-15T19:48:03Z","isPatch":false,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Sun, May 15, 2005 at 09:25:06PM CEST, I got a letter\nwhere Junio C Hamano <junkio@cox.net> told me that...\n> >>>>> \"BR\" == Brad Roberts <braddr@puremagic.com> writes:\n> \n> >> I've merged some of the minor stuff for now.\n> \n> BR> Cool, though there appears to have been some objections. :)\n> \n> I do not have any problem with what the _patch_ does at all.  I\n> had more trouble in the process of how the patch appeared in\n> git-pb tree, and I still do.\n> \n> Please consider the revert request retracted.  Request to\n> forewarn people in the mailing list still stands.\n\nWell, it isn't like this was some huge large-scale change; the diff is\nquite small. Do you want me to announce _any_ identifier renames in\nadvance on the mailing list? Or where should be the threshold? These\nwere three renames of not-so-frequently used identifiers.\n\n-- \n\t\t\t\tPetr \"Pasky\" Baudis\nStuff: http://pasky.or.cz/\nC++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor\n"},{"id":"3382","messageId":"Pine.LNX.4.44.0505151309030.2136-100000@bellevue.puremagic.com","threadId":"626","inReplyTo":"20050515194803.GI13024@pasky.ji.cz","subject":"Re: Darcs-git: a few notes for Git hackers","fromName":"Brad Roberts","fromEmail":"braddr@puremagic.com","sentAt":"2005-05-15T20:10:02Z","receivedAt":"2005-05-15T20:10:02Z","isPatch":false,"sender":{"key":"braddr@puremagic.com","avatar":null},"body":"> Date: Sun, 15 May 2005 21:48:03 +0200\n> From: Petr Baudis <pasky@ucw.cz>\n> To: Junio C Hamano <junkio@cox.net>\n> Cc: Brad Roberts <braddr@puremagic.com>,\n>      Juliusz Chroboczek <Juliusz.Chroboczek@pps.jussieu.fr>,\n>      git@vger.kernel.org\n> Subject: Re: Darcs-git: a few notes for Git hackers\n>\n> Dear diary, on Sun, May 15, 2005 at 09:25:06PM CEST, I got a letter\n> where Junio C Hamano <junkio@cox.net> told me that...\n> > >>>>> \"BR\" == Brad Roberts <braddr@puremagic.com> writes:\n> >\n> > >> I've merged some of the minor stuff for now.\n> >\n> > BR> Cool, though there appears to have been some objections. :)\n> >\n> > I do not have any problem with what the _patch_ does at all.  I\n> > had more trouble in the process of how the patch appeared in\n> > git-pb tree, and I still do.\n> >\n> > Please consider the revert request retracted.  Request to\n> > forewarn people in the mailing list still stands.\n>\n> Well, it isn't like this was some huge large-scale change; the diff is\n> quite small. Do you want me to announce _any_ identifier renames in\n> advance on the mailing list? Or where should be the threshold? These\n> were three renames of not-so-frequently used identifiers.\n\nAdditionally, all of these changes were posted originally on 4/22, this\nwas just a bring-forward of them as requested.\n\nLater,\nBrad\n\n"},{"id":"3385","messageId":"7voebcrztl.fsf@assigned-by-dhcp.cox.net","threadId":"626","inReplyTo":"Pine.LNX.4.44.0505151309030.2136-100000@bellevue.puremagic.com","subject":"Re: Darcs-git: a few notes for Git hackers","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-05-15T20:36:54Z","receivedAt":"2005-05-15T20:36:54Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":">>>>> \"BR\" == Brad Roberts <braddr@puremagic.com> writes:\n\nBR> Additionally, all of these changes were posted originally on 4/22, this\nBR> was just a bring-forward of them as requested.\n\nI admit I overreacted without first seeing the extent of damage.\nSorry I made too big a fuss about this.\n\nThe 4/22 one I found very good and expected it to be in good\nshape when finished.  I simply did not expect that to be taken\npiecemeal like Petr did.  I overreacted, thinking he did so\n_without_ considering much about possible conflicts.\n\nThe request to _continue_ using good judgements when to forewarn\npeople still stands ;-).  In this case, Petr used good\njudgement.  My apologies to both of you if my knee-jerk reaction\ncaused you bad feelings.\n\n"},{"id":"3466","messageId":"20050517201859.GF7136@pasky.ji.cz","threadId":"626","inReplyTo":"7voebcrztl.fsf@assigned-by-dhcp.cox.net","subject":"Re: Darcs-git: a few notes for Git hackers","fromName":"Petr Baudis","fromEmail":"pasky@ucw.cz","sentAt":"2005-05-17T20:19:00Z","receivedAt":"2005-05-17T20:19:00Z","isPatch":false,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Sun, May 15, 2005 at 10:36:54PM CEST, I got a letter\nwhere Junio C Hamano <junkio@cox.net> told me that...\n> The request to _continue_ using good judgements when to forewarn\n> people still stands ;-).  In this case, Petr used good\n> judgement.  My apologies to both of you if my knee-jerk reaction\n> caused you bad feelings.\n\nNo problem here. I'm of course going to consult the mailing list on any\nlarger-scale code changes.\n\n-- \n\t\t\t\tPetr \"Pasky\" Baudis\nStuff: http://pasky.or.cz/\nC++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor\n"},{"id":"3467","messageId":"20050517202150.GG7136@pasky.ji.cz","threadId":"626","inReplyTo":"Pine.LNX.4.44.0505151204230.2136-100000@bellevue.puremagic.com","subject":"Re: Darcs-git: a few notes for Git hackers","fromName":"Petr Baudis","fromEmail":"pasky@ucw.cz","sentAt":"2005-05-17T20:21:50Z","receivedAt":"2005-05-17T20:21:50Z","isPatch":false,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Sun, May 15, 2005 at 09:06:27PM CEST, I got a letter\nwhere Brad Roberts <braddr@puremagic.com> told me that...\n> > > 2) Should the index changing areas be constructing a new index instead of\n> > > shuffling bits within the current index?\n> >\n> > When I have a big cache (the only time it matters), I do usually only\n> > relatively small changes to it, so...\n> \n> The entire index is bit shuffled around even if nothing changed.  At least\n> today, size and amount changed doesn't matter.\n\nAt the very least, it probably shouldn't get shuffled around if there\nare no changes whatsoever.\n\n> > I'd imagine the plan of attack to continue by changing active_cache to\n> > be struct cache, then making it local.\n> \n> Which is what the rest of that patch does.\n\nWell, the important word there was \"then\". :-) I think the patch is too\nbig, do you think it would be possible to separate it to those two\nstages? (I could do it on my own when I get enough time, but who knows\nwhen that happens... ;-)\n\nThanks,\n\n-- \n\t\t\t\tPetr \"Pasky\" Baudis\nStuff: http://pasky.or.cz/\nC++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor\n"}]}