Merge branch 'jk/has-uncommitted-changes-fix'
authorJunio C Hamano <gitster@pobox.com>
Thu, 2 Aug 2018 22:30:37 +0000 (15:30 -0700)
committerJunio C Hamano <gitster@pobox.com>
Thu, 2 Aug 2018 22:30:38 +0000 (15:30 -0700)
"git pull --rebase" on a corrupt HEAD caused a segfault. In
general we substitute an empty tree object when running the in-core
equivalent of the diff-index command, and the codepath has been
corrected to do so as well to fix this issue.

* jk/has-uncommitted-changes-fix:
has_uncommitted_changes(): fall back to empty tree

diff-lib.c
t/t5520-pull.sh
wt-status.c
index a9f38eb5a3e0e17d111301b581d06876ce5fd510..732f684a49c54cdbc3b9708e91c064b7845d7716 100644 (file)
@@ -520,6 +520,9 @@ int run_diff_index(struct rev_info *revs, int cached)
        struct object_array_entry *ent;
        uint64_t start = getnanotime();
 
+       if (revs->pending.nr != 1)
+               BUG("run_diff_index must be passed exactly one tree");
+
        ent = revs->pending.objects;
        if (diff_cache(revs, &ent->item->oid, ent->name, cached))
                exit(128);
index 59c4b778d3a455b6ef4575a4b07b860d1e84720d..68aa5f0340132e8d3fabfd85aa70f1cdfe755cf3 100755 (executable)
@@ -618,6 +618,18 @@ test_expect_success 'pull --rebase fails on unborn branch with staged changes' '
        )
 '
 
+test_expect_success 'pull --rebase fails on corrupt HEAD' '
+       test_when_finished "rm -rf corrupt" &&
+       git init corrupt &&
+       (
+               cd corrupt &&
+               test_commit one &&
+               obj=$(git rev-parse --verify HEAD | sed "s#^..#&/#") &&
+               rm -f .git/objects/$obj &&
+               test_must_fail git pull --rebase
+       )
+'
+
 test_expect_success 'setup for detecting upstreamed changes' '
        mkdir src &&
        (cd src &&
index 8827a256d32925ea24d51ccf00f3108154d01757..fadbed0de9710643ac595f551f2897133b05f8c9 100644 (file)
@@ -2340,7 +2340,17 @@ int has_uncommitted_changes(int ignore_submodules)
        if (ignore_submodules)
                rev_info.diffopt.flags.ignore_submodules = 1;
        rev_info.diffopt.flags.quick = 1;
+
        add_head_to_pending(&rev_info);
+       if (!rev_info.pending.nr) {
+               /*
+                * We have no head (or it's corrupt); use the empty tree,
+                * which will complain if the index is non-empty.
+                */
+               struct tree *tree = lookup_tree(the_hash_algo->empty_tree);
+               add_pending_object(&rev_info, &tree->object, "");
+       }
+
        diff_setup_done(&rev_info.diffopt);
        result = run_diff_index(&rev_info, 1);
        return diff_result_code(&rev_info.diffopt, result);