summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/reader.c13
-rw-r--r--tests/apply/both.c17
2 files changed, 30 insertions, 0 deletions
diff --git a/src/reader.c b/src/reader.c
index 5de731bea..026bc2b51 100644
--- a/src/reader.c
+++ b/src/reader.c
@@ -79,6 +79,8 @@ static int workdir_reader_read(
{
workdir_reader *reader = (workdir_reader *)_reader;
git_buf path = GIT_BUF_INIT;
+ struct stat st;
+ git_filemode_t filemode;
git_filter_list *filters = NULL;
const git_index_entry *idx_entry;
git_oid id;
@@ -88,6 +90,16 @@ static int workdir_reader_read(
git_repository_workdir(reader->repo), filename)) < 0)
goto done;
+ if ((error = p_lstat(path.ptr, &st)) < 0) {
+ if (error == -1 && errno == ENOENT)
+ error = GIT_ENOTFOUND;
+
+ giterr_set(GITERR_OS, "could not stat '%s'", path.ptr);
+ goto done;
+ }
+
+ filemode = git_futils_canonical_mode(st.st_mode);
+
/*
* Patch application - for example - uses the filtered version of
* the working directory data to match git. So we will run the
@@ -108,6 +120,7 @@ static int workdir_reader_read(
if (reader->index) {
if (!(idx_entry = git_index_get_bypath(reader->index, filename, 0)) ||
+ filemode != idx_entry->mode ||
!git_oid_equal(&id, &idx_entry->id)) {
error = GIT_READER_MISMATCH;
goto done;
diff --git a/tests/apply/both.c b/tests/apply/both.c
index e8d13c763..abbabbdcb 100644
--- a/tests/apply/both.c
+++ b/tests/apply/both.c
@@ -204,6 +204,23 @@ void test_apply_both__index_must_match_workdir(void)
git_diff_free(diff);
}
+void test_apply_both__index_mode_must_match_workdir(void)
+{
+ git_diff *diff;
+
+ if (!cl_is_chmod_supported())
+ clar__skip();
+
+ /* Set a file in the working directory executable. */
+ cl_must_pass(p_chmod("merge-recursive/asparagus.txt", 0755));
+
+ cl_git_pass(git_diff_from_buffer(&diff, DIFF_MODIFY_TWO_FILES,
+ strlen(DIFF_MODIFY_TWO_FILES)));
+ cl_git_fail_with(GIT_EAPPLYFAIL, git_apply(repo, diff, GIT_APPLY_LOCATION_BOTH, NULL));
+
+ git_diff_free(diff);
+}
+
void test_apply_both__application_failure_leaves_workdir_unmodified(void)
{
git_diff *diff;