Imported Upstream version 2.7.0
[platform/upstream/git.git] / unpack-trees.c
index 17a5eeb..8e2032f 100644 (file)
@@ -9,6 +9,7 @@
 #include "refs.h"
 #include "attr.h"
 #include "split-index.h"
+#include "dir.h"
 
 /*
  * Error messages expected by scripts out of plumbing commands such as
@@ -223,6 +224,9 @@ static int check_updates(struct unpack_trees_options *o)
                struct cache_entry *ce = index->cache[i];
 
                if (ce->ce_flags & CE_UPDATE) {
+                       if (ce->ce_flags & CE_WT_REMOVE)
+                               die("BUG: both update and delete flags are set on %s",
+                                   ce->name);
                        display_progress(progress, ++cnt);
                        ce->ce_flags &= ~CE_UPDATE;
                        if (o->update && !o->dry_run) {
@@ -292,6 +296,7 @@ static int apply_sparse_checkout(struct index_state *istate,
                if (!(ce->ce_flags & CE_UPDATE) && verify_uptodate_sparse(ce, o))
                        return -1;
                ce->ce_flags |= CE_WT_REMOVE;
+               ce->ce_flags &= ~CE_UPDATE;
        }
        if (was_skip_worktree && !ce_skip_worktree(ce)) {
                if (verify_absent_sparse(ce, ERROR_WOULD_LOSE_UNTRACKED_OVERWRITTEN, o))
@@ -1024,10 +1029,12 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
        if (!core_apply_sparse_checkout || !o->update)
                o->skip_sparse_checkout = 1;
        if (!o->skip_sparse_checkout) {
-               if (add_excludes_from_file_to_list(git_path("info/sparse-checkout"), "", 0, &el, 0) < 0)
+               char *sparse = git_pathdup("info/sparse-checkout");
+               if (add_excludes_from_file_to_list(sparse, "", 0, &el, 0) < 0)
                        o->skip_sparse_checkout = 1;
                else
                        o->el = &el;
+               free(sparse);
        }
 
        memset(&o->result, 0, sizeof(o->result));
@@ -1155,6 +1162,14 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
        o->src_index = NULL;
        ret = check_updates(o) ? (-2) : 0;
        if (o->dst_index) {
+               if (!ret) {
+                       if (!o->result.cache_tree)
+                               o->result.cache_tree = cache_tree();
+                       if (!cache_tree_fully_valid(o->result.cache_tree))
+                               cache_tree_update(&o->result,
+                                                 WRITE_TREE_SILENT |
+                                                 WRITE_TREE_REPAIR);
+               }
                discard_index(o->dst_index);
                *o->dst_index = o->result;
        } else {
@@ -1259,8 +1274,10 @@ static int verify_uptodate_sparse(const struct cache_entry *ce,
 static void invalidate_ce_path(const struct cache_entry *ce,
                               struct unpack_trees_options *o)
 {
-       if (ce)
-               cache_tree_invalidate_path(o->src_index, ce->name);
+       if (!ce)
+               return;
+       cache_tree_invalidate_path(o->src_index, ce->name);
+       untracked_cache_invalidate_path(o->src_index, ce->name);
 }
 
 /*
@@ -1333,9 +1350,7 @@ static int verify_clean_subdirectory(const struct cache_entry *ce,
         * Then we need to make sure that we do not lose a locally
         * present file that is not ignored.
         */
-       pathbuf = xmalloc(namelen + 2);
-       memcpy(pathbuf, ce->name, namelen);
-       strcpy(pathbuf+namelen, "/");
+       pathbuf = xstrfmt("%.*s/", namelen, ce->name);
 
        memset(&d, 0, sizeof(d));
        if (o->dir)