diff options
| author | Edward Thomson <ethomson@edwardthomson.com> | 2018-06-09 18:36:21 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-06-09 18:36:21 +0100 |
| commit | 795a5b28ad1f6e5dfd82d45bd7721914f49d31d3 (patch) | |
| tree | 350786a9984128dea7e18fbfd41a8bb7e56e55b0 | |
| parent | f81923efbeab1290e7a069446f62f9794cf6d408 (diff) | |
| parent | 5a7d454bf657fdf4d726f2319bf554ffd4486ed3 (diff) | |
| download | libgit2-795a5b28ad1f6e5dfd82d45bd7721914f49d31d3.tar.gz | |
Merge pull request #4668 from novalis/bad-stash
Fix stash save bug with fast path index check
| -rw-r--r-- | src/diff_generate.c | 3 | ||||
| -rw-r--r-- | tests/stash/save.c | 40 |
2 files changed, 42 insertions, 1 deletions
diff --git a/src/diff_generate.c b/src/diff_generate.c index e11cbe4e4..0105c1701 100644 --- a/src/diff_generate.c +++ b/src/diff_generate.c @@ -273,7 +273,8 @@ static git_diff_delta *diff_delta__last_for_item( break; case GIT_DELTA_MODIFIED: if (git_oid__cmp(&delta->old_file.id, &item->id) == 0 || - git_oid__cmp(&delta->new_file.id, &item->id) == 0) + (delta->new_file.mode == item->mode && + git_oid__cmp(&delta->new_file.id, &item->id) == 0)) return delta; break; default: diff --git a/tests/stash/save.c b/tests/stash/save.c index edcee820f..5c2d494d2 100644 --- a/tests/stash/save.c +++ b/tests/stash/save.c @@ -188,6 +188,46 @@ void test_stash_save__can_include_untracked_and_ignored_files(void) cl_assert(!git_path_exists("stash/just.ignore")); } +/* + * Note: this test was flaky prior to fixing #4101 -- run it several + * times to get a failure. The issues is that whether the fast + * (stat-only) codepath is used inside stash's diff operation depends + * on whether files are "racily clean", and there doesn't seem to be + * an easy way to force the exact required state. + */ +void test_stash_save__untracked_regression(void) +{ + git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; + const char *paths[] = {"what", "where", "how", "why"}; + git_reference *head; + git_commit *head_commit; + git_buf untracked_dir; + + const char* workdir = git_repository_workdir(repo); + + git_buf_init(&untracked_dir, 0); + git_buf_printf(&untracked_dir, "%sz", workdir); + + cl_assert(!p_mkdir(untracked_dir.ptr, 0777)); + + cl_git_pass(git_repository_head(&head, repo)); + + cl_git_pass(git_reference_peel((git_object **)&head_commit, head, GIT_OBJ_COMMIT)); + + opts.checkout_strategy = GIT_CHECKOUT_FORCE; + + opts.paths.strings = (char **)paths; + opts.paths.count = 4; + + cl_git_pass(git_checkout_tree(repo, (git_object*)head_commit, &opts)); + + cl_git_pass(git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_DEFAULT)); + + assert_commit_message_contains("refs/stash", "WIP on master"); + + git_buf_free(&untracked_dir); +} + #define MESSAGE "Look Ma! I'm on TV!" void test_stash_save__can_accept_a_message(void) { |
