Merge branch 'master' into jc/cache-tree
authorJunio C Hamano <junkio@cox.net>
Wed, 26 Apr 2006 10:29:09 +0000 (03:29 -0700)
committerJunio C Hamano <junkio@cox.net>
Wed, 26 Apr 2006 10:29:09 +0000 (03:29 -0700)
* master:
  commit-tree: allow generic object name for the tree as well.
  Makefile: remove and create xdiff library from scratch.
  t0000-basic: Add ls-tree recursive test back.
  Libified diff-index: backward compatibility fix.
  Libify diff-index.
  Libify diff-files.
  Makefile: remove and create libgit.a from scratch.
  Document the configuration file
  Document git-var -l listing also configuration variables
  rev-parse: better error message for ambiguous arguments
  make update-index --chmod work with multiple files and --stdin
  socksetup: don't return on set_reuse_addr() error
  Fix "git show --stat"
  git-update-index --unresolve
  Add git-unresolve <paths>...
  Add colordiff for git to contrib/colordiff.
  gitk: Let git-rev-list do the argument list parsing

1  2 
Makefile
update-index.c

diff --combined Makefile
+++ b/Makefile
@@@ -199,12 -199,12 +199,12 @@@ LIB_H = 
        tree-walk.h log-tree.h
  
  DIFF_OBJS = \
-       diff-lib.o diffcore-break.o diffcore-order.o \
+       diff.o diff-lib.o diffcore-break.o diffcore-order.o \
        diffcore-pickaxe.o diffcore-rename.o tree-diff.o combine-diff.o \
        diffcore-delta.o log-tree.o
  
  LIB_OBJS = \
 -      blob.o commit.o connect.o csum-file.o \
 +      blob.o commit.o connect.o csum-file.o cache-tree.o \
        date.o diff-delta.o entry.o exec_cmd.o ident.o index.o \
        object.o pack-check.o patch-delta.o path.o pkt-line.o \
        quote.o read-cache.o refs.o run-command.o \
@@@ -575,12 -575,12 +575,12 @@@ $(patsubst git-%$X,%.o,$(PROGRAMS)): $(
  $(DIFF_OBJS): diffcore.h
  
  $(LIB_FILE): $(LIB_OBJS)
-       $(AR) rcs $@ $(LIB_OBJS)
+       rm -f $@ && $(AR) rcs $@ $(LIB_OBJS)
  
  XDIFF_OBJS=xdiff/xdiffi.o xdiff/xprepare.o xdiff/xutils.o xdiff/xemit.o
  
  $(XDIFF_LIB): $(XDIFF_OBJS)
-       $(AR) rcs $@ $(XDIFF_OBJS)
+       rm -f $@ && $(AR) rcs $@ $(XDIFF_OBJS)
  
  
  doc:
@@@ -611,9 -611,6 +611,9 @@@ test-date$X: test-date.c date.o ctype.
  test-delta$X: test-delta.c diff-delta.o patch-delta.o
        $(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $^ -lz
  
 +test-dump-cache-tree$X: dump-cache-tree.o $(GITLIBS)
 +      $(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
 +
  check:
        for i in *.c; do sparse $(ALL_CFLAGS) $(SPARSE_FLAGS) $$i || exit; done
  
diff --combined update-index.c
@@@ -6,7 -6,7 +6,8 @@@
  #include "cache.h"
  #include "strbuf.h"
  #include "quote.h"
 +#include "cache-tree.h"
+ #include "tree-walk.h"
  
  /*
   * Default to not allowing changes to the list of files. The
@@@ -71,7 -71,6 +72,7 @@@ static int mark_valid(const char *path
                        active_cache[pos]->ce_flags &= ~htons(CE_VALID);
                        break;
                }
 +              cache_tree_invalidate_path(active_cache_tree, path);
                active_cache_changed = 1;
                return 0;
        }
@@@ -85,12 -84,6 +86,12 @@@ static int add_file_to_cache(const cha
        struct stat st;
  
        status = lstat(path, &st);
 +
 +      /* We probably want to do this in remove_file_from_cache() and
 +       * add_cache_entry() instead...
 +       */
 +      cache_tree_invalidate_path(active_cache_tree, path);
 +
        if (status < 0 || S_ISDIR(st.st_mode)) {
                /* When we used to have "path" and now we want to add
                 * "path/file", we need a way to remove "path" before
@@@ -333,11 -326,10 +334,11 @@@ static int add_cacheinfo(unsigned int m
                return error("%s: cannot add to the index - missing --add option?",
                             path);
        report("add '%s'", path);
 +      cache_tree_invalidate_path(active_cache_tree, path);
        return 0;
  }
  
- static int chmod_path(int flip, const char *path)
+ static void chmod_path(int flip, const char *path)
  {
        int pos;
        struct cache_entry *ce;
  
        pos = cache_name_pos(path, strlen(path));
        if (pos < 0)
-               return -1;
+               goto fail;
        ce = active_cache[pos];
        mode = ntohl(ce->ce_mode);
        if (!S_ISREG(mode))
-               return -1;
+               goto fail;
        switch (flip) {
        case '+':
                ce->ce_mode |= htonl(0111); break;
        case '-':
                ce->ce_mode &= htonl(~0111); break;
        default:
-               return -1;
+               goto fail;
        }
 +      cache_tree_invalidate_path(active_cache_tree, path);
        active_cache_changed = 1;
-       return 0;
+       report("chmod %cx '%s'", flip, path);
+       return;
+  fail:
+       die("git-update-index: cannot chmod %cx '%s'", flip, path);
  }
  
  static struct cache_file cache_file;
@@@ -377,7 -371,6 +381,7 @@@ static void update_one(const char *path
                        die("Unable to mark file %s", path);
                return;
        }
 +      cache_tree_invalidate_path(active_cache_tree, path);
  
        if (force_remove) {
                if (remove_file_from_cache(p))
@@@ -453,7 -446,6 +457,7 @@@ static void read_index_info(int line_te
                                free(path_name);
                        continue;
                }
 +              cache_tree_invalidate_path(active_cache_tree, path_name);
  
                if (!mode) {
                        /* mode == 0 means there is no such path -- remove */
  static const char update_index_usage[] =
  "git-update-index [-q] [--add] [--replace] [--remove] [--unmerged] [--refresh] [--cacheinfo] [--chmod=(+|-)x] [--info-only] [--force-remove] [--stdin] [--index-info] [--ignore-missing] [-z] [--verbose] [--] <file>...";
  
+ static unsigned char head_sha1[20];
+ static unsigned char merge_head_sha1[20];
+ static struct cache_entry *read_one_ent(const char *which,
+                                       unsigned char *ent, const char *path,
+                                       int namelen, int stage)
+ {
+       unsigned mode;
+       unsigned char sha1[20];
+       int size;
+       struct cache_entry *ce;
+       if (get_tree_entry(ent, path, sha1, &mode)) {
+               error("%s: not in %s branch.", path, which);
+               return NULL;
+       }
+       if (mode == S_IFDIR) {
+               error("%s: not a blob in %s branch.", path, which);
+               return NULL;
+       }
+       size = cache_entry_size(namelen);
+       ce = xcalloc(1, size);
+       memcpy(ce->sha1, sha1, 20);
+       memcpy(ce->name, path, namelen);
+       ce->ce_flags = create_ce_flags(namelen, stage);
+       ce->ce_mode = create_ce_mode(mode);
+       return ce;
+ }
+ static int unresolve_one(const char *path)
+ {
+       int namelen = strlen(path);
+       int pos;
+       int ret = 0;
+       struct cache_entry *ce_2 = NULL, *ce_3 = NULL;
+       /* See if there is such entry in the index. */
+       pos = cache_name_pos(path, namelen);
+       if (pos < 0) {
+               /* If there isn't, either it is unmerged, or
+                * resolved as "removed" by mistake.  We do not
+                * want to do anything in the former case.
+                */
+               pos = -pos-1;
+               if (pos < active_nr) {
+                       struct cache_entry *ce = active_cache[pos];
+                       if (ce_namelen(ce) == namelen &&
+                           !memcmp(ce->name, path, namelen)) {
+                               fprintf(stderr,
+                                       "%s: skipping still unmerged path.\n",
+                                       path);
+                               goto free_return;
+                       }
+               }
+       }
+       /* Grab blobs from given path from HEAD and MERGE_HEAD,
+        * stuff HEAD version in stage #2,
+        * stuff MERGE_HEAD version in stage #3.
+        */
+       ce_2 = read_one_ent("our", head_sha1, path, namelen, 2);
+       ce_3 = read_one_ent("their", merge_head_sha1, path, namelen, 3);
+       if (!ce_2 || !ce_3) {
+               ret = -1;
+               goto free_return;
+       }
+       if (!memcmp(ce_2->sha1, ce_3->sha1, 20) &&
+           ce_2->ce_mode == ce_3->ce_mode) {
+               fprintf(stderr, "%s: identical in both, skipping.\n",
+                       path);
+               goto free_return;
+       }
+       remove_file_from_cache(path);
+       if (add_cache_entry(ce_2, ADD_CACHE_OK_TO_ADD)) {
+               error("%s: cannot add our version to the index.", path);
+               ret = -1;
+               goto free_return;
+       }
+       if (!add_cache_entry(ce_3, ADD_CACHE_OK_TO_ADD))
+               return 0;
+       error("%s: cannot add their version to the index.", path);
+       ret = -1;
+  free_return:
+       free(ce_2);
+       free(ce_3);
+       return ret;
+ }
+ static void read_head_pointers(void)
+ {
+       if (read_ref(git_path("HEAD"), head_sha1))
+               die("No HEAD -- no initial commit yet?\n");
+       if (read_ref(git_path("MERGE_HEAD"), merge_head_sha1)) {
+               fprintf(stderr, "Not in the middle of a merge.\n");
+               exit(0);
+       }
+ }
+ static int do_unresolve(int ac, const char **av)
+ {
+       int i;
+       int err = 0;
+       /* Read HEAD and MERGE_HEAD; if MERGE_HEAD does not exist, we
+        * are not doing a merge, so exit with success status.
+        */
+       read_head_pointers();
+       for (i = 1; i < ac; i++) {
+               const char *arg = av[i];
+               err |= unresolve_one(arg);
+       }
+       return err;
+ }
  int main(int argc, const char **argv)
  {
        int i, newfd, entries, has_errors = 0, line_termination = '\n';
        int read_from_stdin = 0;
        const char *prefix = setup_git_directory();
        int prefix_length = prefix ? strlen(prefix) : 0;
+       char set_executable_bit = 0;
  
        git_config(git_default_config);
  
                            !strcmp(path, "--chmod=+x")) {
                                if (argc <= i+1)
                                        die("git-update-index: %s <path>", path);
-                               if (chmod_path(path[8], argv[++i]))
-                                       die("git-update-index: %s cannot chmod %s", path, argv[i]);
+                               set_executable_bit = path[8];
                                continue;
                        }
                        if (!strcmp(path, "--assume-unchanged")) {
                                read_index_info(line_termination);
                                break;
                        }
+                       if (!strcmp(path, "--unresolve")) {
+                               has_errors = do_unresolve(argc - i, argv + i);
+                               if (has_errors)
+                                       active_cache_changed = 0;
+                               goto finish;
+                       }
                        if (!strcmp(path, "--ignore-missing")) {
                                not_new = 1;
                                continue;
                        die("unknown option %s", path);
                }
                update_one(path, prefix, prefix_length);
+               if (set_executable_bit)
+                       chmod_path(set_executable_bit, path);
        }
        if (read_from_stdin) {
                struct strbuf buf;
                        else
                                path_name = buf.buf;
                        update_one(path_name, prefix, prefix_length);
+                       if (set_executable_bit) {
+                               const char *p = prefix_path(prefix, prefix_length, path_name);
+                               chmod_path(set_executable_bit, p);
+                       }
                        if (path_name != buf.buf)
                                free(path_name);
                }
        }
+  finish:
        if (active_cache_changed) {
                if (write_cache(newfd, active_cache, active_nr) ||
                    commit_index_file(&cache_file))