Merge branch 'rs/unpack-trees-tree-walk-conflict-field'
authorJunio C Hamano <gitster@pobox.com>
Mon, 24 Jun 2013 20:48:44 +0000 (13:48 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 24 Jun 2013 20:48:44 +0000 (13:48 -0700)
Code clean-up.

* rs/unpack-trees-tree-walk-conflict-field:
unpack-trees: don't shift conflicts left and right

1  2 
unpack-trees.c
diff --combined unpack-trees.c
index 57b40743a1ae047de6837d70124298a49dc668e7,96226e275acbae17e207d104c4d671ceb167c8c4..b27f2a62e8c462a95229486342323500de4d5ca0
@@@ -116,20 -116,14 +116,20 @@@ static void do_add_entry(struct unpack_
                        ADD_CACHE_OK_TO_ADD | ADD_CACHE_OK_TO_REPLACE);
  }
  
 -static void add_entry(struct unpack_trees_options *o, struct cache_entry *ce,
 -      unsigned int set, unsigned int clear)
 +static struct cache_entry *dup_entry(const struct cache_entry *ce)
  {
        unsigned int size = ce_size(ce);
        struct cache_entry *new = xmalloc(size);
  
        memcpy(new, ce, size);
 -      do_add_entry(o, new, set, clear);
 +      return new;
 +}
 +
 +static void add_entry(struct unpack_trees_options *o,
 +                    const struct cache_entry *ce,
 +                    unsigned int set, unsigned int clear)
 +{
 +      do_add_entry(o, dup_entry(ce), set, clear);
  }
  
  /*
@@@ -241,11 -235,8 +241,11 @@@ static int check_updates(struct unpack_
        return errs != 0;
  }
  
 -static int verify_uptodate_sparse(struct cache_entry *ce, struct unpack_trees_options *o);
 -static int verify_absent_sparse(struct cache_entry *ce, enum unpack_trees_error_types, struct unpack_trees_options *o);
 +static int verify_uptodate_sparse(const struct cache_entry *ce,
 +                                struct unpack_trees_options *o);
 +static int verify_absent_sparse(const struct cache_entry *ce,
 +                              enum unpack_trees_error_types,
 +                              struct unpack_trees_options *o);
  
  static int apply_sparse_checkout(struct cache_entry *ce, struct unpack_trees_options *o)
  {
        return 0;
  }
  
 -static inline int call_unpack_fn(struct cache_entry **src, struct unpack_trees_options *o)
 +static inline int call_unpack_fn(const struct cache_entry * const *src,
 +                               struct unpack_trees_options *o)
  {
        int ret = o->fn(src, o);
        if (ret > 0)
@@@ -330,7 -320,7 +330,7 @@@ static void mark_all_ce_unused(struct i
                index->cache[i]->ce_flags &= ~(CE_UNPACKED | CE_ADDED | CE_NEW_SKIP_WORKTREE);
  }
  
 -static int locate_in_src_index(struct cache_entry *ce,
 +static int locate_in_src_index(const struct cache_entry *ce,
                               struct unpack_trees_options *o)
  {
        struct index_state *index = o->src_index;
@@@ -398,7 -388,7 +398,7 @@@ static void add_same_unmerged(struct ca
  static int unpack_index_entry(struct cache_entry *ce,
                              struct unpack_trees_options *o)
  {
 -      struct cache_entry *src[MAX_UNPACK_TREES + 1] = { NULL, };
 +      const struct cache_entry *src[MAX_UNPACK_TREES + 1] = { NULL, };
        int ret;
  
        src[0] = ce;
@@@ -464,7 -454,7 +464,7 @@@ static int traverse_trees_recursive(in
        newinfo.pathspec = info->pathspec;
        newinfo.name = *p;
        newinfo.pathlen += tree_entry_len(p) + 1;
-       newinfo.conflicts |= df_conflicts;
+       newinfo.df_conflicts |= df_conflicts;
  
        for (i = 0; i < n; i++, dirmask >>= 1) {
                const unsigned char *sha1 = NULL;
@@@ -565,17 -555,12 +565,12 @@@ static int unpack_nondirectories(int n
  {
        int i;
        struct unpack_trees_options *o = info->data;
-       unsigned long conflicts;
+       unsigned long conflicts = info->df_conflicts | dirmask;
  
        /* Do we have *only* directories? Nothing to do */
        if (mask == dirmask && !src[0])
                return 0;
  
-       conflicts = info->conflicts;
-       if (o->merge)
-               conflicts >>= 1;
-       conflicts |= dirmask;
        /*
         * Ok, we've filled in up to any potential index entry in src[0],
         * now do the rest.
                src[i + o->merge] = create_ce_entry(info, names + i, stage);
        }
  
 -      if (o->merge)
 -              return call_unpack_fn(src, o);
 +      if (o->merge) {
 +              int rc = call_unpack_fn((const struct cache_entry * const *)src,
 +                                      o);
 +              for (i = 0; i < n; i++) {
 +                      struct cache_entry *ce = src[i + o->merge];
 +                      if (ce != o->df_conflict_entry)
 +                              free(ce);
 +              }
 +              return rc;
 +      }
  
        for (i = 0; i < n; i++)
                if (src[i] && src[i] != o->df_conflict_entry)
@@@ -807,13 -784,6 +802,6 @@@ static int unpack_callback(int n, unsig
  
        /* Now handle any directories.. */
        if (dirmask) {
-               unsigned long conflicts = mask & ~dirmask;
-               if (o->merge) {
-                       conflicts <<= 1;
-                       if (src[0])
-                               conflicts |= 1;
-               }
                /* special case: "diff-index --cached" looking at a tree */
                if (o->diff_index_cached &&
                    n == 1 && dirmask == 1 && S_ISDIR(names->mode)) {
                        }
                }
  
-               if (traverse_trees_recursive(n, dirmask, conflicts,
+               if (traverse_trees_recursive(n, dirmask, mask & ~dirmask,
                                             names, info) < 0)
                        return -1;
                return mask;
@@@ -1013,9 -983,7 +1001,9 @@@ static void mark_new_skip_worktree(stru
                       select_flag, skip_wt_flag, el);
  }
  
 -static int verify_absent(struct cache_entry *, enum unpack_trees_error_types, struct unpack_trees_options *);
 +static int verify_absent(const struct cache_entry *,
 +                       enum unpack_trees_error_types,
 +                       struct unpack_trees_options *);
  /*
   * N-way merge "len" trees.  Returns 0 on success, -1 on failure to manipulate the
   * resulting index, -2 on failure to reflect the changes to the work tree.
@@@ -1185,13 -1153,12 +1173,13 @@@ return_failed
  
  /* Here come the merge functions */
  
 -static int reject_merge(struct cache_entry *ce, struct unpack_trees_options *o)
 +static int reject_merge(const struct cache_entry *ce,
 +                      struct unpack_trees_options *o)
  {
        return add_rejected_path(o, ERROR_WOULD_OVERWRITE, ce->name);
  }
  
 -static int same(struct cache_entry *a, struct cache_entry *b)
 +static int same(const struct cache_entry *a, const struct cache_entry *b)
  {
        if (!!a != !!b)
                return 0;
   * When a CE gets turned into an unmerged entry, we
   * want it to be up-to-date
   */
 -static int verify_uptodate_1(struct cache_entry *ce,
 -                                 struct unpack_trees_options *o,
 -                                 enum unpack_trees_error_types error_type)
 +static int verify_uptodate_1(const struct cache_entry *ce,
 +                           struct unpack_trees_options *o,
 +                           enum unpack_trees_error_types error_type)
  {
        struct stat st;
  
                add_rejected_path(o, error_type, ce->name);
  }
  
 -static int verify_uptodate(struct cache_entry *ce,
 +static int verify_uptodate(const struct cache_entry *ce,
                           struct unpack_trees_options *o)
  {
        if (!o->skip_sparse_checkout && (ce->ce_flags & CE_NEW_SKIP_WORKTREE))
        return verify_uptodate_1(ce, o, ERROR_NOT_UPTODATE_FILE);
  }
  
 -static int verify_uptodate_sparse(struct cache_entry *ce,
 +static int verify_uptodate_sparse(const struct cache_entry *ce,
                                  struct unpack_trees_options *o)
  {
        return verify_uptodate_1(ce, o, ERROR_SPARSE_NOT_UPTODATE_FILE);
  }
  
 -static void invalidate_ce_path(struct cache_entry *ce, struct unpack_trees_options *o)
 +static void invalidate_ce_path(const struct cache_entry *ce,
 +                             struct unpack_trees_options *o)
  {
        if (ce)
                cache_tree_invalidate_path(o->src_index->cache_tree, ce->name);
   * Currently, git does not checkout subprojects during a superproject
   * checkout, so it is not going to overwrite anything.
   */
 -static int verify_clean_submodule(struct cache_entry *ce,
 -                                    enum unpack_trees_error_types error_type,
 -                                    struct unpack_trees_options *o)
 +static int verify_clean_submodule(const struct cache_entry *ce,
 +                                enum unpack_trees_error_types error_type,
 +                                struct unpack_trees_options *o)
  {
        return 0;
  }
  
 -static int verify_clean_subdirectory(struct cache_entry *ce,
 -                                    enum unpack_trees_error_types error_type,
 -                                    struct unpack_trees_options *o)
 +static int verify_clean_subdirectory(const struct cache_entry *ce,
 +                                   enum unpack_trees_error_types error_type,
 +                                   struct unpack_trees_options *o)
  {
        /*
         * we are about to extract "ce->name"; we would not want to lose
@@@ -1372,7 -1338,7 +1360,7 @@@ static int icase_exists(struct unpack_t
  }
  
  static int check_ok_to_remove(const char *name, int len, int dtype,
 -                            struct cache_entry *ce, struct stat *st,
 +                            const struct cache_entry *ce, struct stat *st,
                              enum unpack_trees_error_types error_type,
                              struct unpack_trees_options *o)
  {
   * We do not want to remove or overwrite a working tree file that
   * is not tracked, unless it is ignored.
   */
 -static int verify_absent_1(struct cache_entry *ce,
 -                               enum unpack_trees_error_types error_type,
 -                               struct unpack_trees_options *o)
 +static int verify_absent_1(const struct cache_entry *ce,
 +                         enum unpack_trees_error_types error_type,
 +                         struct unpack_trees_options *o)
  {
        int len;
        struct stat st;
        }
  }
  
 -static int verify_absent(struct cache_entry *ce,
 +static int verify_absent(const struct cache_entry *ce,
                         enum unpack_trees_error_types error_type,
                         struct unpack_trees_options *o)
  {
        return verify_absent_1(ce, error_type, o);
  }
  
 -static int verify_absent_sparse(struct cache_entry *ce,
 -                       enum unpack_trees_error_types error_type,
 -                       struct unpack_trees_options *o)
 +static int verify_absent_sparse(const struct cache_entry *ce,
 +                              enum unpack_trees_error_types error_type,
 +                              struct unpack_trees_options *o)
  {
        enum unpack_trees_error_types orphaned_error = error_type;
        if (orphaned_error == ERROR_WOULD_LOSE_UNTRACKED_OVERWRITTEN)
        return verify_absent_1(ce, orphaned_error, o);
  }
  
 -static int merged_entry(struct cache_entry *merge, struct cache_entry *old,
 -              struct unpack_trees_options *o)
 +static int merged_entry(const struct cache_entry *ce,
 +                      const struct cache_entry *old,
 +                      struct unpack_trees_options *o)
  {
        int update = CE_UPDATE;
 +      struct cache_entry *merge = dup_entry(ce);
  
        if (!old) {
                /*
                update |= CE_ADDED;
                merge->ce_flags |= CE_NEW_SKIP_WORKTREE;
  
 -              if (verify_absent(merge, ERROR_WOULD_LOSE_UNTRACKED_OVERWRITTEN, o))
 +              if (verify_absent(merge,
 +                                ERROR_WOULD_LOSE_UNTRACKED_OVERWRITTEN, o)) {
 +                      free(merge);
                        return -1;
 +              }
                invalidate_ce_path(merge, o);
        } else if (!(old->ce_flags & CE_CONFLICTED)) {
                /*
                        copy_cache_entry(merge, old);
                        update = 0;
                } else {
 -                      if (verify_uptodate(old, o))
 +                      if (verify_uptodate(old, o)) {
 +                              free(merge);
                                return -1;
 +                      }
                        /* Migrate old flags over */
                        update |= old->ce_flags & (CE_SKIP_WORKTREE | CE_NEW_SKIP_WORKTREE);
                        invalidate_ce_path(old, o);
                invalidate_ce_path(old, o);
        }
  
 -      add_entry(o, merge, update, CE_STAGEMASK);
 +      do_add_entry(o, merge, update, CE_STAGEMASK);
        return 1;
  }
  
 -static int deleted_entry(struct cache_entry *ce, struct cache_entry *old,
 -              struct unpack_trees_options *o)
 +static int deleted_entry(const struct cache_entry *ce,
 +                       const struct cache_entry *old,
 +                       struct unpack_trees_options *o)
  {
        /* Did it exist in the index? */
        if (!old) {
        return 1;
  }
  
 -static int keep_entry(struct cache_entry *ce, struct unpack_trees_options *o)
 +static int keep_entry(const struct cache_entry *ce,
 +                    struct unpack_trees_options *o)
  {
        add_entry(o, ce, 0, 0);
        return 1;
@@@ -1583,12 -1540,11 +1571,12 @@@ static void show_stage_entry(FILE *o
  }
  #endif
  
 -int threeway_merge(struct cache_entry **stages, struct unpack_trees_options *o)
 +int threeway_merge(const struct cache_entry * const *stages,
 +                 struct unpack_trees_options *o)
  {
 -      struct cache_entry *index;
 -      struct cache_entry *head;
 -      struct cache_entry *remote = stages[o->head_idx + 1];
 +      const struct cache_entry *index;
 +      const struct cache_entry *head;
 +      const struct cache_entry *remote = stages[o->head_idx + 1];
        int count;
        int head_match = 0;
        int remote_match = 0;
        if (o->aggressive) {
                int head_deleted = !head;
                int remote_deleted = !remote;
 -              struct cache_entry *ce = NULL;
 +              const struct cache_entry *ce = NULL;
  
                if (index)
                        ce = index;
   * "carry forward" rule, please see <Documentation/git-read-tree.txt>.
   *
   */
 -int twoway_merge(struct cache_entry **src, struct unpack_trees_options *o)
 +int twoway_merge(const struct cache_entry * const *src,
 +               struct unpack_trees_options *o)
  {
 -      struct cache_entry *current = src[0];
 -      struct cache_entry *oldtree = src[1];
 -      struct cache_entry *newtree = src[2];
 +      const struct cache_entry *current = src[0];
 +      const struct cache_entry *oldtree = src[1];
 +      const struct cache_entry *newtree = src[2];
  
        if (o->merge_size != 2)
                return error("Cannot do a twoway merge of %d trees",
   * Keep the index entries at stage0, collapse stage1 but make sure
   * stage0 does not have anything there.
   */
 -int bind_merge(struct cache_entry **src,
 -              struct unpack_trees_options *o)
 +int bind_merge(const struct cache_entry * const *src,
 +             struct unpack_trees_options *o)
  {
 -      struct cache_entry *old = src[0];
 -      struct cache_entry *a = src[1];
 +      const struct cache_entry *old = src[0];
 +      const struct cache_entry *a = src[1];
  
        if (o->merge_size != 1)
                return error("Cannot do a bind merge of %d trees",
   * The rule is:
   * - take the stat information from stage0, take the data from stage1
   */
 -int oneway_merge(struct cache_entry **src, struct unpack_trees_options *o)
 +int oneway_merge(const struct cache_entry * const *src,
 +               struct unpack_trees_options *o)
  {
 -      struct cache_entry *old = src[0];
 -      struct cache_entry *a = src[1];
 +      const struct cache_entry *old = src[0];
 +      const struct cache_entry *a = src[1];
  
        if (o->merge_size != 1)
                return error("Cannot do a oneway merge of %d trees",