diff: check files with the same or newer timestamps

When a file on the workdir has the same or a newer timestamp than the
index, we need to perform a full check of the contents, as the update of
the file may have happened just after we wrote the index.

The iterator changes are such that we can reach inside the workdir
iterator from the diff, though it may be better to have an accessor
instead of moving these structs into the header.
This commit is contained in:
Carlos Martín Nieto
2015-06-22 12:47:30 +02:00
parent e96a97f18e
commit ff47537557
6 changed files with 61 additions and 3 deletions
+33
View File
@@ -1,4 +1,5 @@
#include "clar_libgit2.h"
#include "../checkout/checkout_helpers.h"
#include "buffer.h"
@@ -37,3 +38,35 @@ void test_diff_racy__diff(void)
cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, index, NULL));
cl_assert_equal_i(1, git_diff_num_deltas(diff));
}
void test_diff_racy__write_index_just_after_file(void)
{
git_index *index;
git_diff *diff;
git_buf path = GIT_BUF_INIT;
/* Make sure we do have a timestamp */
cl_git_pass(git_repository_index(&index, g_repo));
cl_git_pass(git_index_write(index));
/* The timestamp will be one second before we change the file */
sleep(1);
cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "A"));
cl_git_mkfile(path.ptr, "A");
/*
* Put 'A' into the index, the size field will be filled,
* because the index' on-disk timestamp does not match the
* file's timestamp. Both timestamps will however match after
* writing out the index.
*/
cl_git_pass(git_repository_index(&index, g_repo));
cl_git_pass(git_index_add_bypath(index, "A"));
cl_git_pass(git_index_write(index));
/* Change its contents quickly, so we get the same timestamp */
cl_git_mkfile(path.ptr, "B");
cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, index, NULL));
cl_assert_equal_i(1, git_diff_num_deltas(diff));
}
+2
View File
@@ -1623,6 +1623,8 @@ void test_diff_workdir__can_update_index(void)
/* now if we do it again, we should see fewer OID calculations */
/* tick again as the index updating from the previous diff might have reset the timestamp */
tick_index(index);
basic_diff_status(&diff, &opts);
cl_git_pass(git_diff_get_perfdata(&perf, diff));