summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@edwardthomson.com>2018-06-09 18:36:21 +0100
committerGitHub <noreply@github.com>2018-06-09 18:36:21 +0100
commit795a5b28ad1f6e5dfd82d45bd7721914f49d31d3 (patch)
tree350786a9984128dea7e18fbfd41a8bb7e56e55b0
parentf81923efbeab1290e7a069446f62f9794cf6d408 (diff)
parent5a7d454bf657fdf4d726f2319bf554ffd4486ed3 (diff)
downloadlibgit2-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.c3
-rw-r--r--tests/stash/save.c40
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)
{