Merge branch 'en/unpack-trees-split-index-fix'
authorJunio C Hamano <gitster@pobox.com>
Wed, 23 May 2018 05:38:22 +0000 (14:38 +0900)
committerJunio C Hamano <gitster@pobox.com>
Wed, 23 May 2018 05:38:22 +0000 (14:38 +0900)
The split-index feature had a long-standing and dormant bug in
certain use of the in-core merge machinery, which has been fixed.

* en/unpack-trees-split-index-fix:
unpack_trees: fix breakage when o->src_index != o->dst_index

1  2 
unpack-trees.c
diff --combined unpack-trees.c
index 3b6c3eeccd00de82606279b99a4a82aa906c199f,49526d70aa9a6d25ce072c6ca87356311e188420..0f01be60047fff034fed2280981e1ad70abf6ed9
@@@ -290,7 -290,7 +290,7 @@@ static void load_gitmodules_file(struc
                if (!state && ce->ce_flags & CE_WT_REMOVE) {
                        repo_read_gitmodules(the_repository);
                } else if (state && (ce->ce_flags & CE_UPDATE)) {
 -                      submodule_free();
 +                      submodule_free(the_repository);
                        checkout_entry(ce, state, NULL);
                        repo_read_gitmodules(the_repository);
                }
@@@ -1284,9 -1284,20 +1284,20 @@@ int unpack_trees(unsigned len, struct t
        o->result.timestamp.sec = o->src_index->timestamp.sec;
        o->result.timestamp.nsec = o->src_index->timestamp.nsec;
        o->result.version = o->src_index->version;
-       o->result.split_index = o->src_index->split_index;
-       if (o->result.split_index)
+       if (!o->src_index->split_index) {
+               o->result.split_index = NULL;
+       } else if (o->src_index == o->dst_index) {
+               /*
+                * o->dst_index (and thus o->src_index) will be discarded
+                * and overwritten with o->result at the end of this function,
+                * so just use src_index's split_index to avoid having to
+                * create a new one.
+                */
+               o->result.split_index = o->src_index->split_index;
                o->result.split_index->refcount++;
+       } else {
+               o->result.split_index = init_split_index(&o->result);
+       }
        hashcpy(o->result.sha1, o->src_index->sha1);
        o->merge_size = len;
        mark_all_ce_unused(o->src_index);
                }
        }
  
-       o->src_index = NULL;
        ret = check_updates(o) ? (-2) : 0;
        if (o->dst_index) {
                if (!ret) {
                                                  WRITE_TREE_SILENT |
                                                  WRITE_TREE_REPAIR);
                }
-               move_index_extensions(&o->result, o->dst_index);
+               move_index_extensions(&o->result, o->src_index);
                discard_index(o->dst_index);
                *o->dst_index = o->result;
        } else {
                discard_index(&o->result);
        }
+       o->src_index = NULL;
  
  done:
        clear_exclude_list(&el);
@@@ -1509,8 -1520,8 +1520,8 @@@ static int verify_uptodate_1(const stru
                add_rejected_path(o, error_type, ce->name);
  }
  
 -static int verify_uptodate(const struct cache_entry *ce,
 -                         struct unpack_trees_options *o)
 +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 0;