{"thread":{"id":"4256","subject":"[PATCH 4/8] Builtin git-read-tree.","startedAt":"2006-05-23T08:31:16Z","lastAt":"2006-05-23T08:31:16Z","messageCount":1,"participants":["Peter Eriksen"],"isPatch":true,"patchVersion":1,"patchTotal":8},"messages":[{"id":"20523","messageId":"3871.87933451987$1148373109@news.gmane.org","threadId":"4256","inReplyTo":"11483730801352-git-send-email-","subject":"[PATCH 4/8] Builtin git-read-tree.","fromName":"Peter Eriksen","fromEmail":"s022018@student.dtu.dk","sentAt":"2006-05-23T08:31:16Z","receivedAt":"2006-05-23T08:31:16Z","isPatch":true,"sender":{"key":"s022018@student.dtu.dk","avatar":null},"body":"From: Peter Eriksen <s022018@student.dtu.dk>\n\nSigned-off-by: Peter Eriksen <s022018@student.dtu.dk>\n\n\n---\n\nbaba8c18d8a5fff876d16a434b49677cd3ebbdb0\n Makefile            |    6 \n builtin-read-tree.c |  882 +++++++++++++++++++++++++++++++++++++++++++++++++++\n builtin.h           |    1 \n git.c               |    3 \n read-tree.c         |  881 ---------------------------------------------------\n 5 files changed, 888 insertions(+), 885 deletions(-)\n create mode 100644 builtin-read-tree.c\n delete mode 100644 read-tree.c\n\nbaba8c18d8a5fff876d16a434b49677cd3ebbdb0\ndiff --git a/Makefile b/Makefile\nindex 966f7ee..667fa5d 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -157,7 +157,7 @@ PROGRAMS = \\\n \tgit-hash-object$X git-index-pack$X git-local-fetch$X \\\n \tgit-mailinfo$X git-merge-base$X \\\n \tgit-merge-index$X git-mktag$X git-mktree$X git-pack-objects$X git-patch-id$X \\\n-\tgit-peek-remote$X git-prune-packed$X git-read-tree$X \\\n+\tgit-peek-remote$X git-prune-packed$X \\\n \tgit-receive-pack$X git-rev-parse$X \\\n \tgit-send-pack$X git-show-branch$X git-shell$X \\\n \tgit-show-index$X git-ssh-fetch$X \\\n@@ -172,7 +172,7 @@ BUILT_INS = git-log$X git-whatchanged$X \n \tgit-count-objects$X git-diff$X git-push$X \\\n \tgit-grep$X git-rev-list$X git-check-ref-format$X \\\n \tgit-init-db$X git-ls-files$X git-ls-tree$X \\\n-\tgit-tar-tree$X\n+\tgit-tar-tree$X git-read-tree$X\n \n # what 'all' will build and 'install' will install, in gitexecdir\n ALL_PROGRAMS = $(PROGRAMS) $(SIMPLE_PROGRAMS) $(SCRIPTS)\n@@ -222,7 +222,7 @@ BUILTIN_OBJS = \\\n \tbuiltin-log.o builtin-help.o builtin-count.o builtin-diff.o builtin-push.o \\\n \tbuiltin-grep.o builtin-rev-list.o builtin-check-ref-format.o \\\n \tbuiltin-init-db.o builtin-ls-files.o builtin-ls-tree.o \\\n-        builtin-tar-tree.o\n+        builtin-tar-tree.o builtin-read-tree.o\n \n GITLIBS = $(LIB_FILE) $(XDIFF_LIB)\n LIBS = $(GITLIBS) -lz\ndiff --git a/builtin-read-tree.c b/builtin-read-tree.c\nnew file mode 100644\nindex 0000000..ec40d01\n--- /dev/null\n+++ b/builtin-read-tree.c\n@@ -0,0 +1,882 @@\n+/*\n+ * GIT - The information manager from hell\n+ *\n+ * Copyright (C) Linus Torvalds, 2005\n+ */\n+#define DBRT_DEBUG 1\n+\n+#include \"cache.h\"\n+\n+#include \"object.h\"\n+#include \"tree.h\"\n+#include <sys/time.h>\n+#include <signal.h>\n+#include \"builtin.h\"\n+\n+static int reset = 0;\n+static int merge = 0;\n+static int update = 0;\n+static int index_only = 0;\n+static int nontrivial_merge = 0;\n+static int trivial_merges_only = 0;\n+static int aggressive = 0;\n+static int verbose_update = 0;\n+static volatile int progress_update = 0;\n+\n+static int head_idx = -1;\n+static int merge_size = 0;\n+\n+static struct object_list *trees = NULL;\n+\n+static struct cache_entry df_conflict_entry = { \n+};\n+\n+static struct tree_entry_list df_conflict_list = {\n+\t.name = NULL,\n+\t.next = &df_conflict_list\n+};\n+\n+typedef int (*merge_fn_t)(struct cache_entry **src);\n+\n+static int entcmp(char *name1, int dir1, char *name2, int dir2)\n+{\n+\tint len1 = strlen(name1);\n+\tint len2 = strlen(name2);\n+\tint len = len1 < len2 ? len1 : len2;\n+\tint ret = memcmp(name1, name2, len);\n+\tunsigned char c1, c2;\n+\tif (ret)\n+\t\treturn ret;\n+\tc1 = name1[len];\n+\tc2 = name2[len];\n+\tif (!c1 && dir1)\n+\t\tc1 = '/';\n+\tif (!c2 && dir2)\n+\t\tc2 = '/';\n+\tret = (c1 < c2) ? -1 : (c1 > c2) ? 1 : 0;\n+\tif (c1 && c2 && !ret)\n+\t\tret = len1 - len2;\n+\treturn ret;\n+}\n+\n+static int unpack_trees_rec(struct tree_entry_list **posns, int len,\n+\t\t\t    const char *base, merge_fn_t fn, int *indpos)\n+{\n+\tint baselen = strlen(base);\n+\tint src_size = len + 1;\n+\tdo {\n+\t\tint i;\n+\t\tchar *first;\n+\t\tint firstdir = 0;\n+\t\tint pathlen;\n+\t\tunsigned ce_size;\n+\t\tstruct tree_entry_list **subposns;\n+\t\tstruct cache_entry **src;\n+\t\tint any_files = 0;\n+\t\tint any_dirs = 0;\n+\t\tchar *cache_name;\n+\t\tint ce_stage;\n+\n+\t\t/* Find the first name in the input. */\n+\n+\t\tfirst = NULL;\n+\t\tcache_name = NULL;\n+\n+\t\t/* Check the cache */\n+\t\tif (merge && *indpos < active_nr) {\n+\t\t\t/* This is a bit tricky: */\n+\t\t\t/* If the index has a subdirectory (with\n+\t\t\t * contents) as the first name, it'll get a\n+\t\t\t * filename like \"foo/bar\". But that's after\n+\t\t\t * \"foo\", so the entry in trees will get\n+\t\t\t * handled first, at which point we'll go into\n+\t\t\t * \"foo\", and deal with \"bar\" from the index,\n+\t\t\t * because the base will be \"foo/\". The only\n+\t\t\t * way we can actually have \"foo/bar\" first of\n+\t\t\t * all the things is if the trees don't\n+\t\t\t * contain \"foo\" at all, in which case we'll\n+\t\t\t * handle \"foo/bar\" without going into the\n+\t\t\t * directory, but that's fine (and will return\n+\t\t\t * an error anyway, with the added unknown\n+\t\t\t * file case.\n+\t\t\t */\n+\n+\t\t\tcache_name = active_cache[*indpos]->name;\n+\t\t\tif (strlen(cache_name) > baselen &&\n+\t\t\t    !memcmp(cache_name, base, baselen)) {\n+\t\t\t\tcache_name += baselen;\n+\t\t\t\tfirst = cache_name;\n+\t\t\t} else {\n+\t\t\t\tcache_name = NULL;\n+\t\t\t}\n+\t\t}\n+\n+#if DBRT_DEBUG > 1\n+\t\tif (first)\n+\t\t\tprintf(\"index %s\\n\", first);\n+#endif\n+\t\tfor (i = 0; i < len; i++) {\n+\t\t\tif (!posns[i] || posns[i] == &df_conflict_list)\n+\t\t\t\tcontinue;\n+#if DBRT_DEBUG > 1\n+\t\t\tprintf(\"%d %s\\n\", i + 1, posns[i]->name);\n+#endif\n+\t\t\tif (!first || entcmp(first, firstdir,\n+\t\t\t\t\t     posns[i]->name, \n+\t\t\t\t\t     posns[i]->directory) > 0) {\n+\t\t\t\tfirst = posns[i]->name;\n+\t\t\t\tfirstdir = posns[i]->directory;\n+\t\t\t}\n+\t\t}\n+\t\t/* No name means we're done */\n+\t\tif (!first)\n+\t\t\treturn 0;\n+\n+\t\tpathlen = strlen(first);\n+\t\tce_size = cache_entry_size(baselen + pathlen);\n+\n+\t\tsrc = xcalloc(src_size, sizeof(struct cache_entry *));\n+\n+\t\tsubposns = xcalloc(len, sizeof(struct tree_list_entry *));\n+\n+\t\tif (cache_name && !strcmp(cache_name, first)) {\n+\t\t\tany_files = 1;\n+\t\t\tsrc[0] = active_cache[*indpos];\n+\t\t\tremove_cache_entry_at(*indpos);\n+\t\t}\n+\n+\t\tfor (i = 0; i < len; i++) {\n+\t\t\tstruct cache_entry *ce;\n+\n+\t\t\tif (!posns[i] ||\n+\t\t\t    (posns[i] != &df_conflict_list &&\n+\t\t\t     strcmp(first, posns[i]->name))) {\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\n+\t\t\tif (posns[i] == &df_conflict_list) {\n+\t\t\t\tsrc[i + merge] = &df_conflict_entry;\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\n+\t\t\tif (posns[i]->directory) {\n+\t\t\t\tany_dirs = 1;\n+\t\t\t\tparse_tree(posns[i]->item.tree);\n+\t\t\t\tsubposns[i] = posns[i]->item.tree->entries;\n+\t\t\t\tposns[i] = posns[i]->next;\n+\t\t\t\tsrc[i + merge] = &df_conflict_entry;\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\n+\t\t\tif (!merge)\n+\t\t\t\tce_stage = 0;\n+\t\t\telse if (i + 1 < head_idx)\n+\t\t\t\tce_stage = 1;\n+\t\t\telse if (i + 1 > head_idx)\n+\t\t\t\tce_stage = 3;\n+\t\t\telse\n+\t\t\t\tce_stage = 2;\n+\n+\t\t\tce = xcalloc(1, ce_size);\n+\t\t\tce->ce_mode = create_ce_mode(posns[i]->mode);\n+\t\t\tce->ce_flags = create_ce_flags(baselen + pathlen,\n+\t\t\t\t\t\t       ce_stage);\n+\t\t\tmemcpy(ce->name, base, baselen);\n+\t\t\tmemcpy(ce->name + baselen, first, pathlen + 1);\n+\n+\t\t\tany_files = 1;\n+\n+\t\t\tmemcpy(ce->sha1, posns[i]->item.any->sha1, 20);\n+\t\t\tsrc[i + merge] = ce;\n+\t\t\tsubposns[i] = &df_conflict_list;\n+\t\t\tposns[i] = posns[i]->next;\n+\t\t}\n+\t\tif (any_files) {\n+\t\t\tif (merge) {\n+\t\t\t\tint ret;\n+\n+#if DBRT_DEBUG > 1\n+\t\t\t\tprintf(\"%s:\\n\", first);\n+\t\t\t\tfor (i = 0; i < src_size; i++) {\n+\t\t\t\t\tprintf(\" %d \", i);\n+\t\t\t\t\tif (src[i])\n+\t\t\t\t\t\tprintf(\"%s\\n\", sha1_to_hex(src[i]->sha1));\n+\t\t\t\t\telse\n+\t\t\t\t\t\tprintf(\"\\n\");\n+\t\t\t\t}\n+#endif\n+\t\t\t\tret = fn(src);\n+\t\t\t\t\n+#if DBRT_DEBUG > 1\n+\t\t\t\tprintf(\"Added %d entries\\n\", ret);\n+#endif\n+\t\t\t\t*indpos += ret;\n+\t\t\t} else {\n+\t\t\t\tfor (i = 0; i < src_size; i++) {\n+\t\t\t\t\tif (src[i]) {\n+\t\t\t\t\t\tadd_cache_entry(src[i], ADD_CACHE_OK_TO_ADD|ADD_CACHE_SKIP_DFCHECK);\n+\t\t\t\t\t}\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t\tif (any_dirs) {\n+\t\t\tchar *newbase = xmalloc(baselen + 2 + pathlen);\n+\t\t\tmemcpy(newbase, base, baselen);\n+\t\t\tmemcpy(newbase + baselen, first, pathlen);\n+\t\t\tnewbase[baselen + pathlen] = '/';\n+\t\t\tnewbase[baselen + pathlen + 1] = '\\0';\n+\t\t\tif (unpack_trees_rec(subposns, len, newbase, fn,\n+\t\t\t\t\t     indpos))\n+\t\t\t\treturn -1;\n+\t\t\tfree(newbase);\n+\t\t}\n+\t\tfree(subposns);\n+\t\tfree(src);\n+\t} while (1);\n+}\n+\n+static void reject_merge(struct cache_entry *ce)\n+{\n+\tdie(\"Entry '%s' would be overwritten by merge. Cannot merge.\", \n+\t    ce->name);\n+}\n+\n+/* Unlink the last component and attempt to remove leading\n+ * directories, in case this unlink is the removal of the\n+ * last entry in the directory -- empty directories are removed.\n+ */\n+static void unlink_entry(char *name)\n+{\n+\tchar *cp, *prev;\n+\n+\tif (unlink(name))\n+\t\treturn;\n+\tprev = NULL;\n+\twhile (1) {\n+\t\tint status;\n+\t\tcp = strrchr(name, '/');\n+\t\tif (prev)\n+\t\t\t*prev = '/';\n+\t\tif (!cp)\n+\t\t\tbreak;\n+\n+\t\t*cp = 0;\n+\t\tstatus = rmdir(name);\n+\t\tif (status) {\n+\t\t\t*cp = '/';\n+\t\t\tbreak;\n+\t\t}\n+\t\tprev = cp;\n+\t}\n+}\n+\n+static void progress_interval(int signum)\n+{\n+\tprogress_update = 1;\n+}\n+\n+static void setup_progress_signal(void)\n+{\n+\tstruct sigaction sa;\n+\tstruct itimerval v;\n+\n+\tmemset(&sa, 0, sizeof(sa));\n+\tsa.sa_handler = progress_interval;\n+\tsigemptyset(&sa.sa_mask);\n+\tsa.sa_flags = SA_RESTART;\n+\tsigaction(SIGALRM, &sa, NULL);\n+\n+\tv.it_interval.tv_sec = 1;\n+\tv.it_interval.tv_usec = 0;\n+\tv.it_value = v.it_interval;\n+\tsetitimer(ITIMER_REAL, &v, NULL);\n+}\n+\n+static void check_updates(struct cache_entry **src, int nr)\n+{\n+\tstatic struct checkout state = {\n+\t\t.base_dir = \"\",\n+\t\t.force = 1,\n+\t\t.quiet = 1,\n+\t\t.refresh_cache = 1,\n+\t};\n+\tunsigned short mask = htons(CE_UPDATE);\n+\tunsigned last_percent = 200, cnt = 0, total = 0;\n+\n+\tif (update && verbose_update) {\n+\t\tfor (total = cnt = 0; cnt < nr; cnt++) {\n+\t\t\tstruct cache_entry *ce = src[cnt];\n+\t\t\tif (!ce->ce_mode || ce->ce_flags & mask)\n+\t\t\t\ttotal++;\n+\t\t}\n+\n+\t\t/* Don't bother doing this for very small updates */\n+\t\tif (total < 250)\n+\t\t\ttotal = 0;\n+\n+\t\tif (total) {\n+\t\t\tfprintf(stderr, \"Checking files out...\\n\");\n+\t\t\tsetup_progress_signal();\n+\t\t\tprogress_update = 1;\n+\t\t}\n+\t\tcnt = 0;\n+\t}\n+\n+\twhile (nr--) {\n+\t\tstruct cache_entry *ce = *src++;\n+\n+\t\tif (total) {\n+\t\t\tif (!ce->ce_mode || ce->ce_flags & mask) {\n+\t\t\t\tunsigned percent;\n+\t\t\t\tcnt++;\n+\t\t\t\tpercent = (cnt * 100) / total;\n+\t\t\t\tif (percent != last_percent ||\n+\t\t\t\t    progress_update) {\n+\t\t\t\t\tfprintf(stderr, \"%4u%% (%u/%u) done\\r\",\n+\t\t\t\t\t\tpercent, cnt, total);\n+\t\t\t\t\tlast_percent = percent;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t\tif (!ce->ce_mode) {\n+\t\t\tif (update)\n+\t\t\t\tunlink_entry(ce->name);\n+\t\t\tcontinue;\n+\t\t}\n+\t\tif (ce->ce_flags & mask) {\n+\t\t\tce->ce_flags &= ~mask;\n+\t\t\tif (update)\n+\t\t\t\tcheckout_entry(ce, &state, NULL);\n+\t\t}\n+\t}\n+\tif (total) {\n+\t\tsignal(SIGALRM, SIG_IGN);\n+\t\tfputc('\\n', stderr);\n+\t}\n+}\n+\n+static int unpack_trees(merge_fn_t fn)\n+{\n+\tint indpos = 0;\n+\tunsigned len = object_list_length(trees);\n+\tstruct tree_entry_list **posns;\n+\tint i;\n+\tstruct object_list *posn = trees;\n+\tmerge_size = len;\n+\n+\tif (len) {\n+\t\tposns = xmalloc(len * sizeof(struct tree_entry_list *));\n+\t\tfor (i = 0; i < len; i++) {\n+\t\t\tposns[i] = ((struct tree *) posn->item)->entries;\n+\t\t\tposn = posn->next;\n+\t\t}\n+\t\tif (unpack_trees_rec(posns, len, \"\", fn, &indpos))\n+\t\t\treturn -1;\n+\t}\n+\n+\tif (trivial_merges_only && nontrivial_merge)\n+\t\tdie(\"Merge requires file-level merging\");\n+\n+\tcheck_updates(active_cache, active_nr);\n+\treturn 0;\n+}\n+\n+static int list_tree(unsigned char *sha1)\n+{\n+\tstruct tree *tree = parse_tree_indirect(sha1);\n+\tif (!tree)\n+\t\treturn -1;\n+\tobject_list_append(&tree->object, &trees);\n+\treturn 0;\n+}\n+\n+static int same(struct cache_entry *a, struct cache_entry *b)\n+{\n+\tif (!!a != !!b)\n+\t\treturn 0;\n+\tif (!a && !b)\n+\t\treturn 1;\n+\treturn a->ce_mode == b->ce_mode && \n+\t\t!memcmp(a->sha1, b->sha1, 20);\n+}\n+\n+\n+/*\n+ * When a CE gets turned into an unmerged entry, we\n+ * want it to be up-to-date\n+ */\n+static void verify_uptodate(struct cache_entry *ce)\n+{\n+\tstruct stat st;\n+\n+\tif (index_only || reset)\n+\t\treturn;\n+\n+\tif (!lstat(ce->name, &st)) {\n+\t\tunsigned changed = ce_match_stat(ce, &st, 1);\n+\t\tif (!changed)\n+\t\t\treturn;\n+\t\terrno = 0;\n+\t}\n+\tif (reset) {\n+\t\tce->ce_flags |= htons(CE_UPDATE);\n+\t\treturn;\n+\t}\n+\tif (errno == ENOENT)\n+\t\treturn;\n+\tdie(\"Entry '%s' not uptodate. Cannot merge.\", ce->name);\n+}\n+\n+/*\n+ * We do not want to remove or overwrite a working tree file that\n+ * is not tracked.\n+ */\n+static void verify_absent(const char *path, const char *action)\n+{\n+\tstruct stat st;\n+\n+\tif (index_only || reset || !update)\n+\t\treturn;\n+\tif (!lstat(path, &st))\n+\t\tdie(\"Untracked working tree file '%s' \"\n+\t\t    \"would be %s by merge.\", path, action);\n+}\n+\n+static int merged_entry(struct cache_entry *merge, struct cache_entry *old)\n+{\n+\tmerge->ce_flags |= htons(CE_UPDATE);\n+\tif (old) {\n+\t\t/*\n+\t\t * See if we can re-use the old CE directly?\n+\t\t * That way we get the uptodate stat info.\n+\t\t *\n+\t\t * This also removes the UPDATE flag on\n+\t\t * a match.\n+\t\t */\n+\t\tif (same(old, merge)) {\n+\t\t\t*merge = *old;\n+\t\t} else {\n+\t\t\tverify_uptodate(old);\n+\t\t}\n+\t}\n+\telse\n+\t\tverify_absent(merge->name, \"overwritten\");\n+\n+\tmerge->ce_flags &= ~htons(CE_STAGEMASK);\n+\tadd_cache_entry(merge, ADD_CACHE_OK_TO_ADD);\n+\treturn 1;\n+}\n+\n+static int deleted_entry(struct cache_entry *ce, struct cache_entry *old)\n+{\n+\tif (old)\n+\t\tverify_uptodate(old);\n+\telse\n+\t\tverify_absent(ce->name, \"removed\");\n+\tce->ce_mode = 0;\n+\tadd_cache_entry(ce, ADD_CACHE_OK_TO_ADD);\n+\treturn 1;\n+}\n+\n+static int keep_entry(struct cache_entry *ce)\n+{\n+\tadd_cache_entry(ce, ADD_CACHE_OK_TO_ADD);\n+\treturn 1;\n+}\n+\n+#if DBRT_DEBUG\n+static void show_stage_entry(FILE *o,\n+\t\t\t     const char *label, const struct cache_entry *ce)\n+{\n+\tif (!ce)\n+\t\tfprintf(o, \"%s (missing)\\n\", label);\n+\telse\n+\t\tfprintf(o, \"%s%06o %s %d\\t%s\\n\",\n+\t\t\tlabel,\n+\t\t\tntohl(ce->ce_mode),\n+\t\t\tsha1_to_hex(ce->sha1),\n+\t\t\tce_stage(ce),\n+\t\t\tce->name);\n+}\n+#endif\n+\n+static int threeway_merge(struct cache_entry **stages)\n+{\n+\tstruct cache_entry *index;\n+\tstruct cache_entry *head; \n+\tstruct cache_entry *remote = stages[head_idx + 1];\n+\tint count;\n+\tint head_match = 0;\n+\tint remote_match = 0;\n+\tconst char *path = NULL;\n+\n+\tint df_conflict_head = 0;\n+\tint df_conflict_remote = 0;\n+\n+\tint any_anc_missing = 0;\n+\tint no_anc_exists = 1;\n+\tint i;\n+\n+\tfor (i = 1; i < head_idx; i++) {\n+\t\tif (!stages[i])\n+\t\t\tany_anc_missing = 1;\n+\t\telse {\n+\t\t\tif (!path)\n+\t\t\t\tpath = stages[i]->name;\n+\t\t\tno_anc_exists = 0;\n+\t\t}\n+\t}\n+\n+\tindex = stages[0];\n+\thead = stages[head_idx];\n+\n+\tif (head == &df_conflict_entry) {\n+\t\tdf_conflict_head = 1;\n+\t\thead = NULL;\n+\t}\n+\n+\tif (remote == &df_conflict_entry) {\n+\t\tdf_conflict_remote = 1;\n+\t\tremote = NULL;\n+\t}\n+\n+\tif (!path && index)\n+\t\tpath = index->name;\n+\tif (!path && head)\n+\t\tpath = head->name;\n+\tif (!path && remote)\n+\t\tpath = remote->name;\n+\n+\t/* First, if there's a #16 situation, note that to prevent #13\n+\t * and #14.\n+\t */\n+\tif (!same(remote, head)) {\n+\t\tfor (i = 1; i < head_idx; i++) {\n+\t\t\tif (same(stages[i], head)) {\n+\t\t\t\thead_match = i;\n+\t\t\t}\n+\t\t\tif (same(stages[i], remote)) {\n+\t\t\t\tremote_match = i;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\t/* We start with cases where the index is allowed to match\n+\t * something other than the head: #14(ALT) and #2ALT, where it\n+\t * is permitted to match the result instead.\n+\t */\n+\t/* #14, #14ALT, #2ALT */\n+\tif (remote && !df_conflict_head && head_match && !remote_match) {\n+\t\tif (index && !same(index, remote) && !same(index, head))\n+\t\t\treject_merge(index);\n+\t\treturn merged_entry(remote, index);\n+\t}\n+\t/*\n+\t * If we have an entry in the index cache, then we want to\n+\t * make sure that it matches head.\n+\t */\n+\tif (index && !same(index, head)) {\n+\t\treject_merge(index);\n+\t}\n+\n+\tif (head) {\n+\t\t/* #5ALT, #15 */\n+\t\tif (same(head, remote))\n+\t\t\treturn merged_entry(head, index);\n+\t\t/* #13, #3ALT */\n+\t\tif (!df_conflict_remote && remote_match && !head_match)\n+\t\t\treturn merged_entry(head, index);\n+\t}\n+\n+\t/* #1 */\n+\tif (!head && !remote && any_anc_missing)\n+\t\treturn 0;\n+\n+\t/* Under the new \"aggressive\" rule, we resolve mostly trivial\n+\t * cases that we historically had git-merge-one-file resolve.\n+\t */\n+\tif (aggressive) {\n+\t\tint head_deleted = !head && !df_conflict_head;\n+\t\tint remote_deleted = !remote && !df_conflict_remote;\n+\t\t/*\n+\t\t * Deleted in both.\n+\t\t * Deleted in one and unchanged in the other.\n+\t\t */\n+\t\tif ((head_deleted && remote_deleted) ||\n+\t\t    (head_deleted && remote && remote_match) ||\n+\t\t    (remote_deleted && head && head_match)) {\n+\t\t\tif (index)\n+\t\t\t\treturn deleted_entry(index, index);\n+\t\t\telse if (path)\n+\t\t\t\tverify_absent(path, \"removed\");\n+\t\t\treturn 0;\n+\t\t}\n+\t\t/*\n+\t\t * Added in both, identically.\n+\t\t */\n+\t\tif (no_anc_exists && head && remote && same(head, remote))\n+\t\t\treturn merged_entry(head, index);\n+\n+\t}\n+\n+\t/* Below are \"no merge\" cases, which require that the index be\n+\t * up-to-date to avoid the files getting overwritten with\n+\t * conflict resolution files. \n+\t */\n+\tif (index) {\n+\t\tverify_uptodate(index);\n+\t}\n+\telse if (path)\n+\t\tverify_absent(path, \"overwritten\");\n+\n+\tnontrivial_merge = 1;\n+\n+\t/* #2, #3, #4, #6, #7, #9, #11. */\n+\tcount = 0;\n+\tif (!head_match || !remote_match) {\n+\t\tfor (i = 1; i < head_idx; i++) {\n+\t\t\tif (stages[i]) {\n+\t\t\t\tkeep_entry(stages[i]);\n+\t\t\t\tcount++;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t}\n+#if DBRT_DEBUG\n+\telse {\n+\t\tfprintf(stderr, \"read-tree: warning #16 detected\\n\");\n+\t\tshow_stage_entry(stderr, \"head   \", stages[head_match]);\n+\t\tshow_stage_entry(stderr, \"remote \", stages[remote_match]);\n+\t}\n+#endif\n+\tif (head) { count += keep_entry(head); }\n+\tif (remote) { count += keep_entry(remote); }\n+\treturn count;\n+}\n+\n+/*\n+ * Two-way merge.\n+ *\n+ * The rule is to \"carry forward\" what is in the index without losing\n+ * information across a \"fast forward\", favoring a successful merge\n+ * over a merge failure when it makes sense.  For details of the\n+ * \"carry forward\" rule, please see <Documentation/git-read-tree.txt>.\n+ *\n+ */\n+static int twoway_merge(struct cache_entry **src)\n+{\n+\tstruct cache_entry *current = src[0];\n+\tstruct cache_entry *oldtree = src[1], *newtree = src[2];\n+\n+\tif (merge_size != 2)\n+\t\treturn error(\"Cannot do a twoway merge of %d trees\",\n+\t\t\t     merge_size);\n+\n+\tif (current) {\n+\t\tif ((!oldtree && !newtree) || /* 4 and 5 */\n+\t\t    (!oldtree && newtree &&\n+\t\t     same(current, newtree)) || /* 6 and 7 */\n+\t\t    (oldtree && newtree &&\n+\t\t     same(oldtree, newtree)) || /* 14 and 15 */\n+\t\t    (oldtree && newtree &&\n+\t\t     !same(oldtree, newtree) && /* 18 and 19*/\n+\t\t     same(current, newtree))) {\n+\t\t\treturn keep_entry(current);\n+\t\t}\n+\t\telse if (oldtree && !newtree && same(current, oldtree)) {\n+\t\t\t/* 10 or 11 */\n+\t\t\treturn deleted_entry(oldtree, current);\n+\t\t}\n+\t\telse if (oldtree && newtree &&\n+\t\t\t same(current, oldtree) && !same(current, newtree)) {\n+\t\t\t/* 20 or 21 */\n+\t\t\treturn merged_entry(newtree, current);\n+\t\t}\n+\t\telse {\n+\t\t\t/* all other failures */\n+\t\t\tif (oldtree)\n+\t\t\t\treject_merge(oldtree);\n+\t\t\tif (current)\n+\t\t\t\treject_merge(current);\n+\t\t\tif (newtree)\n+\t\t\t\treject_merge(newtree);\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\telse if (newtree)\n+\t\treturn merged_entry(newtree, current);\n+\telse\n+\t\treturn deleted_entry(oldtree, current);\n+}\n+\n+/*\n+ * One-way merge.\n+ *\n+ * The rule is:\n+ * - take the stat information from stage0, take the data from stage1\n+ */\n+static int oneway_merge(struct cache_entry **src)\n+{\n+\tstruct cache_entry *old = src[0];\n+\tstruct cache_entry *a = src[1];\n+\n+\tif (merge_size != 1)\n+\t\treturn error(\"Cannot do a oneway merge of %d trees\",\n+\t\t\t     merge_size);\n+\n+\tif (!a)\n+\t\treturn deleted_entry(old, old);\n+\tif (old && same(old, a)) {\n+\t\tif (reset) {\n+\t\t\tstruct stat st;\n+\t\t\tif (lstat(old->name, &st) ||\n+\t\t\t    ce_match_stat(old, &st, 1))\n+\t\t\t\told->ce_flags |= htons(CE_UPDATE);\n+\t\t}\n+\t\treturn keep_entry(old);\n+\t}\n+\treturn merged_entry(a, old);\n+}\n+\n+static int read_cache_unmerged(void)\n+{\n+\tint i, deleted;\n+\tstruct cache_entry **dst;\n+\n+\tread_cache();\n+\tdst = active_cache;\n+\tdeleted = 0;\n+\tfor (i = 0; i < active_nr; i++) {\n+\t\tstruct cache_entry *ce = active_cache[i];\n+\t\tif (ce_stage(ce)) {\n+\t\t\tdeleted++;\n+\t\t\tcontinue;\n+\t\t}\n+\t\tif (deleted)\n+\t\t\t*dst = ce;\n+\t\tdst++;\n+\t}\n+\tactive_nr -= deleted;\n+\treturn deleted;\n+}\n+\n+static const char read_tree_usage[] = \"git-read-tree (<sha> | -m [--aggressive] [-u | -i] <sha1> [<sha2> [<sha3>]])\";\n+\n+static struct cache_file cache_file;\n+\n+int cmd_read_tree(int argc, const char **argv, char **envp)\n+{\n+\tint i, newfd, stage = 0;\n+\tunsigned char sha1[20];\n+\tmerge_fn_t fn = NULL;\n+\n+\tsetup_git_directory();\n+\tgit_config(git_default_config);\n+\n+\tnewfd = hold_index_file_for_update(&cache_file, get_index_file());\n+\tif (newfd < 0)\n+\t\tdie(\"unable to create new cachefile\");\n+\n+\tgit_config(git_default_config);\n+\n+\tmerge = 0;\n+\treset = 0;\n+\tfor (i = 1; i < argc; i++) {\n+\t\tconst char *arg = argv[i];\n+\n+\t\t/* \"-u\" means \"update\", meaning that a merge will update\n+\t\t * the working tree.\n+\t\t */\n+\t\tif (!strcmp(arg, \"-u\")) {\n+\t\t\tupdate = 1;\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (!strcmp(arg, \"-v\")) {\n+\t\t\tverbose_update = 1;\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\t/* \"-i\" means \"index only\", meaning that a merge will\n+\t\t * not even look at the working tree.\n+\t\t */\n+\t\tif (!strcmp(arg, \"-i\")) {\n+\t\t\tindex_only = 1;\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\t/* This differs from \"-m\" in that we'll silently ignore unmerged entries */\n+\t\tif (!strcmp(arg, \"--reset\")) {\n+\t\t\tif (stage || merge)\n+\t\t\t\tusage(read_tree_usage);\n+\t\t\treset = 1;\n+\t\t\tmerge = 1;\n+\t\t\tstage = 1;\n+\t\t\tread_cache_unmerged();\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (!strcmp(arg, \"--trivial\")) {\n+\t\t\ttrivial_merges_only = 1;\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (!strcmp(arg, \"--aggressive\")) {\n+\t\t\taggressive = 1;\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\t/* \"-m\" stands for \"merge\", meaning we start in stage 1 */\n+\t\tif (!strcmp(arg, \"-m\")) {\n+\t\t\tif (stage || merge)\n+\t\t\t\tusage(read_tree_usage);\n+\t\t\tif (read_cache_unmerged())\n+\t\t\t\tdie(\"you need to resolve your current index first\");\n+\t\t\tstage = 1;\n+\t\t\tmerge = 1;\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\t/* using -u and -i at the same time makes no sense */\n+\t\tif (1 < index_only + update)\n+\t\t\tusage(read_tree_usage);\n+\n+\t\tif (get_sha1(arg, sha1))\n+\t\t\tdie(\"Not a valid object name %s\", arg);\n+\t\tif (list_tree(sha1) < 0)\n+\t\t\tdie(\"failed to unpack tree object %s\", arg);\n+\t\tstage++;\n+\t}\n+\tif ((update||index_only) && !merge)\n+\t\tusage(read_tree_usage);\n+\n+\tif (merge) {\n+\t\tif (stage < 2)\n+\t\t\tdie(\"just how do you expect me to merge %d trees?\", stage-1);\n+\t\tswitch (stage - 1) {\n+\t\tcase 1:\n+\t\t\tfn = oneway_merge;\n+\t\t\tbreak;\n+\t\tcase 2:\n+\t\t\tfn = twoway_merge;\n+\t\t\tbreak;\n+\t\tcase 3:\n+\t\t\tfn = threeway_merge;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tfn = threeway_merge;\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tif (stage - 1 >= 3)\n+\t\t\thead_idx = stage - 2;\n+\t\telse\n+\t\t\thead_idx = 1;\n+\t}\n+\n+\tunpack_trees(fn);\n+\tif (write_cache(newfd, active_cache, active_nr) ||\n+\t    commit_index_file(&cache_file))\n+\t\tdie(\"unable to write new index file\");\n+\treturn 0;\n+}\ndiff --git a/builtin.h b/builtin.h\nindex d210543..88b3523 100644\n--- a/builtin.h\n+++ b/builtin.h\n@@ -30,5 +30,6 @@ extern int cmd_init_db(int argc, const c\n extern int cmd_ls_files(int argc, const char **argv, char **envp);\n extern int cmd_ls_tree(int argc, const char **argv, char **envp);\n extern int cmd_tar_tree(int argc, const char **argv, char **envp);\n+extern int cmd_read_tree(int argc, const char **argv, char **envp);\n \n #endif\ndiff --git a/git.c b/git.c\nindex c253e60..300e2b2 100644\n--- a/git.c\n+++ b/git.c\n@@ -55,7 +55,8 @@ static void handle_internal_command(int \n \t\t{ \"check-ref-format\", cmd_check_ref_format },\n \t\t{ \"ls-files\", cmd_ls_files },\n \t\t{ \"ls-tree\", cmd_ls_tree },\n-\t\t{ \"tar-tree\", cmd_tar_tree }\n+\t\t{ \"tar-tree\", cmd_tar_tree },\n+\t\t{ \"read-tree\", cmd_read_tree }\n \t};\n \tint i;\n \ndiff --git a/read-tree.c b/read-tree.c\ndeleted file mode 100644\nindex 82e2a9a..0000000\n--- a/read-tree.c\n+++ /dev/null\n@@ -1,881 +0,0 @@\n-/*\n- * GIT - The information manager from hell\n- *\n- * Copyright (C) Linus Torvalds, 2005\n- */\n-#define DBRT_DEBUG 1\n-\n-#include \"cache.h\"\n-\n-#include \"object.h\"\n-#include \"tree.h\"\n-#include <sys/time.h>\n-#include <signal.h>\n-\n-static int reset = 0;\n-static int merge = 0;\n-static int update = 0;\n-static int index_only = 0;\n-static int nontrivial_merge = 0;\n-static int trivial_merges_only = 0;\n-static int aggressive = 0;\n-static int verbose_update = 0;\n-static volatile int progress_update = 0;\n-\n-static int head_idx = -1;\n-static int merge_size = 0;\n-\n-static struct object_list *trees = NULL;\n-\n-static struct cache_entry df_conflict_entry = { \n-};\n-\n-static struct tree_entry_list df_conflict_list = {\n-\t.name = NULL,\n-\t.next = &df_conflict_list\n-};\n-\n-typedef int (*merge_fn_t)(struct cache_entry **src);\n-\n-static int entcmp(char *name1, int dir1, char *name2, int dir2)\n-{\n-\tint len1 = strlen(name1);\n-\tint len2 = strlen(name2);\n-\tint len = len1 < len2 ? len1 : len2;\n-\tint ret = memcmp(name1, name2, len);\n-\tunsigned char c1, c2;\n-\tif (ret)\n-\t\treturn ret;\n-\tc1 = name1[len];\n-\tc2 = name2[len];\n-\tif (!c1 && dir1)\n-\t\tc1 = '/';\n-\tif (!c2 && dir2)\n-\t\tc2 = '/';\n-\tret = (c1 < c2) ? -1 : (c1 > c2) ? 1 : 0;\n-\tif (c1 && c2 && !ret)\n-\t\tret = len1 - len2;\n-\treturn ret;\n-}\n-\n-static int unpack_trees_rec(struct tree_entry_list **posns, int len,\n-\t\t\t    const char *base, merge_fn_t fn, int *indpos)\n-{\n-\tint baselen = strlen(base);\n-\tint src_size = len + 1;\n-\tdo {\n-\t\tint i;\n-\t\tchar *first;\n-\t\tint firstdir = 0;\n-\t\tint pathlen;\n-\t\tunsigned ce_size;\n-\t\tstruct tree_entry_list **subposns;\n-\t\tstruct cache_entry **src;\n-\t\tint any_files = 0;\n-\t\tint any_dirs = 0;\n-\t\tchar *cache_name;\n-\t\tint ce_stage;\n-\n-\t\t/* Find the first name in the input. */\n-\n-\t\tfirst = NULL;\n-\t\tcache_name = NULL;\n-\n-\t\t/* Check the cache */\n-\t\tif (merge && *indpos < active_nr) {\n-\t\t\t/* This is a bit tricky: */\n-\t\t\t/* If the index has a subdirectory (with\n-\t\t\t * contents) as the first name, it'll get a\n-\t\t\t * filename like \"foo/bar\". But that's after\n-\t\t\t * \"foo\", so the entry in trees will get\n-\t\t\t * handled first, at which point we'll go into\n-\t\t\t * \"foo\", and deal with \"bar\" from the index,\n-\t\t\t * because the base will be \"foo/\". The only\n-\t\t\t * way we can actually have \"foo/bar\" first of\n-\t\t\t * all the things is if the trees don't\n-\t\t\t * contain \"foo\" at all, in which case we'll\n-\t\t\t * handle \"foo/bar\" without going into the\n-\t\t\t * directory, but that's fine (and will return\n-\t\t\t * an error anyway, with the added unknown\n-\t\t\t * file case.\n-\t\t\t */\n-\n-\t\t\tcache_name = active_cache[*indpos]->name;\n-\t\t\tif (strlen(cache_name) > baselen &&\n-\t\t\t    !memcmp(cache_name, base, baselen)) {\n-\t\t\t\tcache_name += baselen;\n-\t\t\t\tfirst = cache_name;\n-\t\t\t} else {\n-\t\t\t\tcache_name = NULL;\n-\t\t\t}\n-\t\t}\n-\n-#if DBRT_DEBUG > 1\n-\t\tif (first)\n-\t\t\tprintf(\"index %s\\n\", first);\n-#endif\n-\t\tfor (i = 0; i < len; i++) {\n-\t\t\tif (!posns[i] || posns[i] == &df_conflict_list)\n-\t\t\t\tcontinue;\n-#if DBRT_DEBUG > 1\n-\t\t\tprintf(\"%d %s\\n\", i + 1, posns[i]->name);\n-#endif\n-\t\t\tif (!first || entcmp(first, firstdir,\n-\t\t\t\t\t     posns[i]->name, \n-\t\t\t\t\t     posns[i]->directory) > 0) {\n-\t\t\t\tfirst = posns[i]->name;\n-\t\t\t\tfirstdir = posns[i]->directory;\n-\t\t\t}\n-\t\t}\n-\t\t/* No name means we're done */\n-\t\tif (!first)\n-\t\t\treturn 0;\n-\n-\t\tpathlen = strlen(first);\n-\t\tce_size = cache_entry_size(baselen + pathlen);\n-\n-\t\tsrc = xcalloc(src_size, sizeof(struct cache_entry *));\n-\n-\t\tsubposns = xcalloc(len, sizeof(struct tree_list_entry *));\n-\n-\t\tif (cache_name && !strcmp(cache_name, first)) {\n-\t\t\tany_files = 1;\n-\t\t\tsrc[0] = active_cache[*indpos];\n-\t\t\tremove_cache_entry_at(*indpos);\n-\t\t}\n-\n-\t\tfor (i = 0; i < len; i++) {\n-\t\t\tstruct cache_entry *ce;\n-\n-\t\t\tif (!posns[i] ||\n-\t\t\t    (posns[i] != &df_conflict_list &&\n-\t\t\t     strcmp(first, posns[i]->name))) {\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\n-\t\t\tif (posns[i] == &df_conflict_list) {\n-\t\t\t\tsrc[i + merge] = &df_conflict_entry;\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\n-\t\t\tif (posns[i]->directory) {\n-\t\t\t\tany_dirs = 1;\n-\t\t\t\tparse_tree(posns[i]->item.tree);\n-\t\t\t\tsubposns[i] = posns[i]->item.tree->entries;\n-\t\t\t\tposns[i] = posns[i]->next;\n-\t\t\t\tsrc[i + merge] = &df_conflict_entry;\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\n-\t\t\tif (!merge)\n-\t\t\t\tce_stage = 0;\n-\t\t\telse if (i + 1 < head_idx)\n-\t\t\t\tce_stage = 1;\n-\t\t\telse if (i + 1 > head_idx)\n-\t\t\t\tce_stage = 3;\n-\t\t\telse\n-\t\t\t\tce_stage = 2;\n-\n-\t\t\tce = xcalloc(1, ce_size);\n-\t\t\tce->ce_mode = create_ce_mode(posns[i]->mode);\n-\t\t\tce->ce_flags = create_ce_flags(baselen + pathlen,\n-\t\t\t\t\t\t       ce_stage);\n-\t\t\tmemcpy(ce->name, base, baselen);\n-\t\t\tmemcpy(ce->name + baselen, first, pathlen + 1);\n-\n-\t\t\tany_files = 1;\n-\n-\t\t\tmemcpy(ce->sha1, posns[i]->item.any->sha1, 20);\n-\t\t\tsrc[i + merge] = ce;\n-\t\t\tsubposns[i] = &df_conflict_list;\n-\t\t\tposns[i] = posns[i]->next;\n-\t\t}\n-\t\tif (any_files) {\n-\t\t\tif (merge) {\n-\t\t\t\tint ret;\n-\n-#if DBRT_DEBUG > 1\n-\t\t\t\tprintf(\"%s:\\n\", first);\n-\t\t\t\tfor (i = 0; i < src_size; i++) {\n-\t\t\t\t\tprintf(\" %d \", i);\n-\t\t\t\t\tif (src[i])\n-\t\t\t\t\t\tprintf(\"%s\\n\", sha1_to_hex(src[i]->sha1));\n-\t\t\t\t\telse\n-\t\t\t\t\t\tprintf(\"\\n\");\n-\t\t\t\t}\n-#endif\n-\t\t\t\tret = fn(src);\n-\t\t\t\t\n-#if DBRT_DEBUG > 1\n-\t\t\t\tprintf(\"Added %d entries\\n\", ret);\n-#endif\n-\t\t\t\t*indpos += ret;\n-\t\t\t} else {\n-\t\t\t\tfor (i = 0; i < src_size; i++) {\n-\t\t\t\t\tif (src[i]) {\n-\t\t\t\t\t\tadd_cache_entry(src[i], ADD_CACHE_OK_TO_ADD|ADD_CACHE_SKIP_DFCHECK);\n-\t\t\t\t\t}\n-\t\t\t\t}\n-\t\t\t}\n-\t\t}\n-\t\tif (any_dirs) {\n-\t\t\tchar *newbase = xmalloc(baselen + 2 + pathlen);\n-\t\t\tmemcpy(newbase, base, baselen);\n-\t\t\tmemcpy(newbase + baselen, first, pathlen);\n-\t\t\tnewbase[baselen + pathlen] = '/';\n-\t\t\tnewbase[baselen + pathlen + 1] = '\\0';\n-\t\t\tif (unpack_trees_rec(subposns, len, newbase, fn,\n-\t\t\t\t\t     indpos))\n-\t\t\t\treturn -1;\n-\t\t\tfree(newbase);\n-\t\t}\n-\t\tfree(subposns);\n-\t\tfree(src);\n-\t} while (1);\n-}\n-\n-static void reject_merge(struct cache_entry *ce)\n-{\n-\tdie(\"Entry '%s' would be overwritten by merge. Cannot merge.\", \n-\t    ce->name);\n-}\n-\n-/* Unlink the last component and attempt to remove leading\n- * directories, in case this unlink is the removal of the\n- * last entry in the directory -- empty directories are removed.\n- */\n-static void unlink_entry(char *name)\n-{\n-\tchar *cp, *prev;\n-\n-\tif (unlink(name))\n-\t\treturn;\n-\tprev = NULL;\n-\twhile (1) {\n-\t\tint status;\n-\t\tcp = strrchr(name, '/');\n-\t\tif (prev)\n-\t\t\t*prev = '/';\n-\t\tif (!cp)\n-\t\t\tbreak;\n-\n-\t\t*cp = 0;\n-\t\tstatus = rmdir(name);\n-\t\tif (status) {\n-\t\t\t*cp = '/';\n-\t\t\tbreak;\n-\t\t}\n-\t\tprev = cp;\n-\t}\n-}\n-\n-static void progress_interval(int signum)\n-{\n-\tprogress_update = 1;\n-}\n-\n-static void setup_progress_signal(void)\n-{\n-\tstruct sigaction sa;\n-\tstruct itimerval v;\n-\n-\tmemset(&sa, 0, sizeof(sa));\n-\tsa.sa_handler = progress_interval;\n-\tsigemptyset(&sa.sa_mask);\n-\tsa.sa_flags = SA_RESTART;\n-\tsigaction(SIGALRM, &sa, NULL);\n-\n-\tv.it_interval.tv_sec = 1;\n-\tv.it_interval.tv_usec = 0;\n-\tv.it_value = v.it_interval;\n-\tsetitimer(ITIMER_REAL, &v, NULL);\n-}\n-\n-static void check_updates(struct cache_entry **src, int nr)\n-{\n-\tstatic struct checkout state = {\n-\t\t.base_dir = \"\",\n-\t\t.force = 1,\n-\t\t.quiet = 1,\n-\t\t.refresh_cache = 1,\n-\t};\n-\tunsigned short mask = htons(CE_UPDATE);\n-\tunsigned last_percent = 200, cnt = 0, total = 0;\n-\n-\tif (update && verbose_update) {\n-\t\tfor (total = cnt = 0; cnt < nr; cnt++) {\n-\t\t\tstruct cache_entry *ce = src[cnt];\n-\t\t\tif (!ce->ce_mode || ce->ce_flags & mask)\n-\t\t\t\ttotal++;\n-\t\t}\n-\n-\t\t/* Don't bother doing this for very small updates */\n-\t\tif (total < 250)\n-\t\t\ttotal = 0;\n-\n-\t\tif (total) {\n-\t\t\tfprintf(stderr, \"Checking files out...\\n\");\n-\t\t\tsetup_progress_signal();\n-\t\t\tprogress_update = 1;\n-\t\t}\n-\t\tcnt = 0;\n-\t}\n-\n-\twhile (nr--) {\n-\t\tstruct cache_entry *ce = *src++;\n-\n-\t\tif (total) {\n-\t\t\tif (!ce->ce_mode || ce->ce_flags & mask) {\n-\t\t\t\tunsigned percent;\n-\t\t\t\tcnt++;\n-\t\t\t\tpercent = (cnt * 100) / total;\n-\t\t\t\tif (percent != last_percent ||\n-\t\t\t\t    progress_update) {\n-\t\t\t\t\tfprintf(stderr, \"%4u%% (%u/%u) done\\r\",\n-\t\t\t\t\t\tpercent, cnt, total);\n-\t\t\t\t\tlast_percent = percent;\n-\t\t\t\t}\n-\t\t\t}\n-\t\t}\n-\t\tif (!ce->ce_mode) {\n-\t\t\tif (update)\n-\t\t\t\tunlink_entry(ce->name);\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (ce->ce_flags & mask) {\n-\t\t\tce->ce_flags &= ~mask;\n-\t\t\tif (update)\n-\t\t\t\tcheckout_entry(ce, &state, NULL);\n-\t\t}\n-\t}\n-\tif (total) {\n-\t\tsignal(SIGALRM, SIG_IGN);\n-\t\tfputc('\\n', stderr);\n-\t}\n-}\n-\n-static int unpack_trees(merge_fn_t fn)\n-{\n-\tint indpos = 0;\n-\tunsigned len = object_list_length(trees);\n-\tstruct tree_entry_list **posns;\n-\tint i;\n-\tstruct object_list *posn = trees;\n-\tmerge_size = len;\n-\n-\tif (len) {\n-\t\tposns = xmalloc(len * sizeof(struct tree_entry_list *));\n-\t\tfor (i = 0; i < len; i++) {\n-\t\t\tposns[i] = ((struct tree *) posn->item)->entries;\n-\t\t\tposn = posn->next;\n-\t\t}\n-\t\tif (unpack_trees_rec(posns, len, \"\", fn, &indpos))\n-\t\t\treturn -1;\n-\t}\n-\n-\tif (trivial_merges_only && nontrivial_merge)\n-\t\tdie(\"Merge requires file-level merging\");\n-\n-\tcheck_updates(active_cache, active_nr);\n-\treturn 0;\n-}\n-\n-static int list_tree(unsigned char *sha1)\n-{\n-\tstruct tree *tree = parse_tree_indirect(sha1);\n-\tif (!tree)\n-\t\treturn -1;\n-\tobject_list_append(&tree->object, &trees);\n-\treturn 0;\n-}\n-\n-static int same(struct cache_entry *a, struct cache_entry *b)\n-{\n-\tif (!!a != !!b)\n-\t\treturn 0;\n-\tif (!a && !b)\n-\t\treturn 1;\n-\treturn a->ce_mode == b->ce_mode && \n-\t\t!memcmp(a->sha1, b->sha1, 20);\n-}\n-\n-\n-/*\n- * When a CE gets turned into an unmerged entry, we\n- * want it to be up-to-date\n- */\n-static void verify_uptodate(struct cache_entry *ce)\n-{\n-\tstruct stat st;\n-\n-\tif (index_only || reset)\n-\t\treturn;\n-\n-\tif (!lstat(ce->name, &st)) {\n-\t\tunsigned changed = ce_match_stat(ce, &st, 1);\n-\t\tif (!changed)\n-\t\t\treturn;\n-\t\terrno = 0;\n-\t}\n-\tif (reset) {\n-\t\tce->ce_flags |= htons(CE_UPDATE);\n-\t\treturn;\n-\t}\n-\tif (errno == ENOENT)\n-\t\treturn;\n-\tdie(\"Entry '%s' not uptodate. Cannot merge.\", ce->name);\n-}\n-\n-/*\n- * We do not want to remove or overwrite a working tree file that\n- * is not tracked.\n- */\n-static void verify_absent(const char *path, const char *action)\n-{\n-\tstruct stat st;\n-\n-\tif (index_only || reset || !update)\n-\t\treturn;\n-\tif (!lstat(path, &st))\n-\t\tdie(\"Untracked working tree file '%s' \"\n-\t\t    \"would be %s by merge.\", path, action);\n-}\n-\n-static int merged_entry(struct cache_entry *merge, struct cache_entry *old)\n-{\n-\tmerge->ce_flags |= htons(CE_UPDATE);\n-\tif (old) {\n-\t\t/*\n-\t\t * See if we can re-use the old CE directly?\n-\t\t * That way we get the uptodate stat info.\n-\t\t *\n-\t\t * This also removes the UPDATE flag on\n-\t\t * a match.\n-\t\t */\n-\t\tif (same(old, merge)) {\n-\t\t\t*merge = *old;\n-\t\t} else {\n-\t\t\tverify_uptodate(old);\n-\t\t}\n-\t}\n-\telse\n-\t\tverify_absent(merge->name, \"overwritten\");\n-\n-\tmerge->ce_flags &= ~htons(CE_STAGEMASK);\n-\tadd_cache_entry(merge, ADD_CACHE_OK_TO_ADD);\n-\treturn 1;\n-}\n-\n-static int deleted_entry(struct cache_entry *ce, struct cache_entry *old)\n-{\n-\tif (old)\n-\t\tverify_uptodate(old);\n-\telse\n-\t\tverify_absent(ce->name, \"removed\");\n-\tce->ce_mode = 0;\n-\tadd_cache_entry(ce, ADD_CACHE_OK_TO_ADD);\n-\treturn 1;\n-}\n-\n-static int keep_entry(struct cache_entry *ce)\n-{\n-\tadd_cache_entry(ce, ADD_CACHE_OK_TO_ADD);\n-\treturn 1;\n-}\n-\n-#if DBRT_DEBUG\n-static void show_stage_entry(FILE *o,\n-\t\t\t     const char *label, const struct cache_entry *ce)\n-{\n-\tif (!ce)\n-\t\tfprintf(o, \"%s (missing)\\n\", label);\n-\telse\n-\t\tfprintf(o, \"%s%06o %s %d\\t%s\\n\",\n-\t\t\tlabel,\n-\t\t\tntohl(ce->ce_mode),\n-\t\t\tsha1_to_hex(ce->sha1),\n-\t\t\tce_stage(ce),\n-\t\t\tce->name);\n-}\n-#endif\n-\n-static int threeway_merge(struct cache_entry **stages)\n-{\n-\tstruct cache_entry *index;\n-\tstruct cache_entry *head; \n-\tstruct cache_entry *remote = stages[head_idx + 1];\n-\tint count;\n-\tint head_match = 0;\n-\tint remote_match = 0;\n-\tconst char *path = NULL;\n-\n-\tint df_conflict_head = 0;\n-\tint df_conflict_remote = 0;\n-\n-\tint any_anc_missing = 0;\n-\tint no_anc_exists = 1;\n-\tint i;\n-\n-\tfor (i = 1; i < head_idx; i++) {\n-\t\tif (!stages[i])\n-\t\t\tany_anc_missing = 1;\n-\t\telse {\n-\t\t\tif (!path)\n-\t\t\t\tpath = stages[i]->name;\n-\t\t\tno_anc_exists = 0;\n-\t\t}\n-\t}\n-\n-\tindex = stages[0];\n-\thead = stages[head_idx];\n-\n-\tif (head == &df_conflict_entry) {\n-\t\tdf_conflict_head = 1;\n-\t\thead = NULL;\n-\t}\n-\n-\tif (remote == &df_conflict_entry) {\n-\t\tdf_conflict_remote = 1;\n-\t\tremote = NULL;\n-\t}\n-\n-\tif (!path && index)\n-\t\tpath = index->name;\n-\tif (!path && head)\n-\t\tpath = head->name;\n-\tif (!path && remote)\n-\t\tpath = remote->name;\n-\n-\t/* First, if there's a #16 situation, note that to prevent #13\n-\t * and #14.\n-\t */\n-\tif (!same(remote, head)) {\n-\t\tfor (i = 1; i < head_idx; i++) {\n-\t\t\tif (same(stages[i], head)) {\n-\t\t\t\thead_match = i;\n-\t\t\t}\n-\t\t\tif (same(stages[i], remote)) {\n-\t\t\t\tremote_match = i;\n-\t\t\t}\n-\t\t}\n-\t}\n-\n-\t/* We start with cases where the index is allowed to match\n-\t * something other than the head: #14(ALT) and #2ALT, where it\n-\t * is permitted to match the result instead.\n-\t */\n-\t/* #14, #14ALT, #2ALT */\n-\tif (remote && !df_conflict_head && head_match && !remote_match) {\n-\t\tif (index && !same(index, remote) && !same(index, head))\n-\t\t\treject_merge(index);\n-\t\treturn merged_entry(remote, index);\n-\t}\n-\t/*\n-\t * If we have an entry in the index cache, then we want to\n-\t * make sure that it matches head.\n-\t */\n-\tif (index && !same(index, head)) {\n-\t\treject_merge(index);\n-\t}\n-\n-\tif (head) {\n-\t\t/* #5ALT, #15 */\n-\t\tif (same(head, remote))\n-\t\t\treturn merged_entry(head, index);\n-\t\t/* #13, #3ALT */\n-\t\tif (!df_conflict_remote && remote_match && !head_match)\n-\t\t\treturn merged_entry(head, index);\n-\t}\n-\n-\t/* #1 */\n-\tif (!head && !remote && any_anc_missing)\n-\t\treturn 0;\n-\n-\t/* Under the new \"aggressive\" rule, we resolve mostly trivial\n-\t * cases that we historically had git-merge-one-file resolve.\n-\t */\n-\tif (aggressive) {\n-\t\tint head_deleted = !head && !df_conflict_head;\n-\t\tint remote_deleted = !remote && !df_conflict_remote;\n-\t\t/*\n-\t\t * Deleted in both.\n-\t\t * Deleted in one and unchanged in the other.\n-\t\t */\n-\t\tif ((head_deleted && remote_deleted) ||\n-\t\t    (head_deleted && remote && remote_match) ||\n-\t\t    (remote_deleted && head && head_match)) {\n-\t\t\tif (index)\n-\t\t\t\treturn deleted_entry(index, index);\n-\t\t\telse if (path)\n-\t\t\t\tverify_absent(path, \"removed\");\n-\t\t\treturn 0;\n-\t\t}\n-\t\t/*\n-\t\t * Added in both, identically.\n-\t\t */\n-\t\tif (no_anc_exists && head && remote && same(head, remote))\n-\t\t\treturn merged_entry(head, index);\n-\n-\t}\n-\n-\t/* Below are \"no merge\" cases, which require that the index be\n-\t * up-to-date to avoid the files getting overwritten with\n-\t * conflict resolution files. \n-\t */\n-\tif (index) {\n-\t\tverify_uptodate(index);\n-\t}\n-\telse if (path)\n-\t\tverify_absent(path, \"overwritten\");\n-\n-\tnontrivial_merge = 1;\n-\n-\t/* #2, #3, #4, #6, #7, #9, #11. */\n-\tcount = 0;\n-\tif (!head_match || !remote_match) {\n-\t\tfor (i = 1; i < head_idx; i++) {\n-\t\t\tif (stages[i]) {\n-\t\t\t\tkeep_entry(stages[i]);\n-\t\t\t\tcount++;\n-\t\t\t\tbreak;\n-\t\t\t}\n-\t\t}\n-\t}\n-#if DBRT_DEBUG\n-\telse {\n-\t\tfprintf(stderr, \"read-tree: warning #16 detected\\n\");\n-\t\tshow_stage_entry(stderr, \"head   \", stages[head_match]);\n-\t\tshow_stage_entry(stderr, \"remote \", stages[remote_match]);\n-\t}\n-#endif\n-\tif (head) { count += keep_entry(head); }\n-\tif (remote) { count += keep_entry(remote); }\n-\treturn count;\n-}\n-\n-/*\n- * Two-way merge.\n- *\n- * The rule is to \"carry forward\" what is in the index without losing\n- * information across a \"fast forward\", favoring a successful merge\n- * over a merge failure when it makes sense.  For details of the\n- * \"carry forward\" rule, please see <Documentation/git-read-tree.txt>.\n- *\n- */\n-static int twoway_merge(struct cache_entry **src)\n-{\n-\tstruct cache_entry *current = src[0];\n-\tstruct cache_entry *oldtree = src[1], *newtree = src[2];\n-\n-\tif (merge_size != 2)\n-\t\treturn error(\"Cannot do a twoway merge of %d trees\",\n-\t\t\t     merge_size);\n-\n-\tif (current) {\n-\t\tif ((!oldtree && !newtree) || /* 4 and 5 */\n-\t\t    (!oldtree && newtree &&\n-\t\t     same(current, newtree)) || /* 6 and 7 */\n-\t\t    (oldtree && newtree &&\n-\t\t     same(oldtree, newtree)) || /* 14 and 15 */\n-\t\t    (oldtree && newtree &&\n-\t\t     !same(oldtree, newtree) && /* 18 and 19*/\n-\t\t     same(current, newtree))) {\n-\t\t\treturn keep_entry(current);\n-\t\t}\n-\t\telse if (oldtree && !newtree && same(current, oldtree)) {\n-\t\t\t/* 10 or 11 */\n-\t\t\treturn deleted_entry(oldtree, current);\n-\t\t}\n-\t\telse if (oldtree && newtree &&\n-\t\t\t same(current, oldtree) && !same(current, newtree)) {\n-\t\t\t/* 20 or 21 */\n-\t\t\treturn merged_entry(newtree, current);\n-\t\t}\n-\t\telse {\n-\t\t\t/* all other failures */\n-\t\t\tif (oldtree)\n-\t\t\t\treject_merge(oldtree);\n-\t\t\tif (current)\n-\t\t\t\treject_merge(current);\n-\t\t\tif (newtree)\n-\t\t\t\treject_merge(newtree);\n-\t\t\treturn -1;\n-\t\t}\n-\t}\n-\telse if (newtree)\n-\t\treturn merged_entry(newtree, current);\n-\telse\n-\t\treturn deleted_entry(oldtree, current);\n-}\n-\n-/*\n- * One-way merge.\n- *\n- * The rule is:\n- * - take the stat information from stage0, take the data from stage1\n- */\n-static int oneway_merge(struct cache_entry **src)\n-{\n-\tstruct cache_entry *old = src[0];\n-\tstruct cache_entry *a = src[1];\n-\n-\tif (merge_size != 1)\n-\t\treturn error(\"Cannot do a oneway merge of %d trees\",\n-\t\t\t     merge_size);\n-\n-\tif (!a)\n-\t\treturn deleted_entry(old, old);\n-\tif (old && same(old, a)) {\n-\t\tif (reset) {\n-\t\t\tstruct stat st;\n-\t\t\tif (lstat(old->name, &st) ||\n-\t\t\t    ce_match_stat(old, &st, 1))\n-\t\t\t\told->ce_flags |= htons(CE_UPDATE);\n-\t\t}\n-\t\treturn keep_entry(old);\n-\t}\n-\treturn merged_entry(a, old);\n-}\n-\n-static int read_cache_unmerged(void)\n-{\n-\tint i, deleted;\n-\tstruct cache_entry **dst;\n-\n-\tread_cache();\n-\tdst = active_cache;\n-\tdeleted = 0;\n-\tfor (i = 0; i < active_nr; i++) {\n-\t\tstruct cache_entry *ce = active_cache[i];\n-\t\tif (ce_stage(ce)) {\n-\t\t\tdeleted++;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (deleted)\n-\t\t\t*dst = ce;\n-\t\tdst++;\n-\t}\n-\tactive_nr -= deleted;\n-\treturn deleted;\n-}\n-\n-static const char read_tree_usage[] = \"git-read-tree (<sha> | -m [--aggressive] [-u | -i] <sha1> [<sha2> [<sha3>]])\";\n-\n-static struct cache_file cache_file;\n-\n-int main(int argc, char **argv)\n-{\n-\tint i, newfd, stage = 0;\n-\tunsigned char sha1[20];\n-\tmerge_fn_t fn = NULL;\n-\n-\tsetup_git_directory();\n-\tgit_config(git_default_config);\n-\n-\tnewfd = hold_index_file_for_update(&cache_file, get_index_file());\n-\tif (newfd < 0)\n-\t\tdie(\"unable to create new cachefile\");\n-\n-\tgit_config(git_default_config);\n-\n-\tmerge = 0;\n-\treset = 0;\n-\tfor (i = 1; i < argc; i++) {\n-\t\tconst char *arg = argv[i];\n-\n-\t\t/* \"-u\" means \"update\", meaning that a merge will update\n-\t\t * the working tree.\n-\t\t */\n-\t\tif (!strcmp(arg, \"-u\")) {\n-\t\t\tupdate = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\n-\t\tif (!strcmp(arg, \"-v\")) {\n-\t\t\tverbose_update = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\n-\t\t/* \"-i\" means \"index only\", meaning that a merge will\n-\t\t * not even look at the working tree.\n-\t\t */\n-\t\tif (!strcmp(arg, \"-i\")) {\n-\t\t\tindex_only = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\n-\t\t/* This differs from \"-m\" in that we'll silently ignore unmerged entries */\n-\t\tif (!strcmp(arg, \"--reset\")) {\n-\t\t\tif (stage || merge)\n-\t\t\t\tusage(read_tree_usage);\n-\t\t\treset = 1;\n-\t\t\tmerge = 1;\n-\t\t\tstage = 1;\n-\t\t\tread_cache_unmerged();\n-\t\t\tcontinue;\n-\t\t}\n-\n-\t\tif (!strcmp(arg, \"--trivial\")) {\n-\t\t\ttrivial_merges_only = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\n-\t\tif (!strcmp(arg, \"--aggressive\")) {\n-\t\t\taggressive = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\n-\t\t/* \"-m\" stands for \"merge\", meaning we start in stage 1 */\n-\t\tif (!strcmp(arg, \"-m\")) {\n-\t\t\tif (stage || merge)\n-\t\t\t\tusage(read_tree_usage);\n-\t\t\tif (read_cache_unmerged())\n-\t\t\t\tdie(\"you need to resolve your current index first\");\n-\t\t\tstage = 1;\n-\t\t\tmerge = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\n-\t\t/* using -u and -i at the same time makes no sense */\n-\t\tif (1 < index_only + update)\n-\t\t\tusage(read_tree_usage);\n-\n-\t\tif (get_sha1(arg, sha1))\n-\t\t\tdie(\"Not a valid object name %s\", arg);\n-\t\tif (list_tree(sha1) < 0)\n-\t\t\tdie(\"failed to unpack tree object %s\", arg);\n-\t\tstage++;\n-\t}\n-\tif ((update||index_only) && !merge)\n-\t\tusage(read_tree_usage);\n-\n-\tif (merge) {\n-\t\tif (stage < 2)\n-\t\t\tdie(\"just how do you expect me to merge %d trees?\", stage-1);\n-\t\tswitch (stage - 1) {\n-\t\tcase 1:\n-\t\t\tfn = oneway_merge;\n-\t\t\tbreak;\n-\t\tcase 2:\n-\t\t\tfn = twoway_merge;\n-\t\t\tbreak;\n-\t\tcase 3:\n-\t\t\tfn = threeway_merge;\n-\t\t\tbreak;\n-\t\tdefault:\n-\t\t\tfn = threeway_merge;\n-\t\t\tbreak;\n-\t\t}\n-\n-\t\tif (stage - 1 >= 3)\n-\t\t\thead_idx = stage - 2;\n-\t\telse\n-\t\t\thead_idx = 1;\n-\t}\n-\n-\tunpack_trees(fn);\n-\tif (write_cache(newfd, active_cache, active_nr) ||\n-\t    commit_index_file(&cache_file))\n-\t\tdie(\"unable to write new index file\");\n-\treturn 0;\n-}\n-- \n1.3.3.g288c\n"}]}