reader: optionally validate index matches workdir When using a workdir reader, optionally validate that the index contents match the working directory contents.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
diff --git a/src/apply.c b/src/apply.c
index 0810c02..d4c7dd0 100644
--- a/src/apply.c
+++ b/src/apply.c
@@ -661,7 +661,7 @@ int git_apply(
* in the index.
*/
if (opts.location == GIT_APPLY_LOCATION_WORKDIR)
- error = git_reader_for_workdir(&pre_reader, repo);
+ error = git_reader_for_workdir(&pre_reader, repo, false);
else
error = git_reader_for_index(&pre_reader, repo, NULL);
diff --git a/src/reader.c b/src/reader.c
index 32900df..94faff7 100644
--- a/src/reader.c
+++ b/src/reader.c
@@ -74,6 +74,7 @@ int git_reader_for_tree(git_reader **out, git_tree *tree)
typedef struct {
git_reader reader;
git_repository *repo;
+ git_index *index;
} workdir_reader;
static int workdir_reader_read(
@@ -84,6 +85,8 @@ static int workdir_reader_read(
{
workdir_reader *reader = (workdir_reader *)_reader;
git_buf path = GIT_BUF_INIT;
+ const git_index_entry *idx_entry;
+ git_oid id;
int error;
if ((error = git_buf_joinpath(&path,
@@ -94,8 +97,21 @@ static int workdir_reader_read(
if ((error = git_futils_readbuffer(out, path.ptr)) < 0)
goto done;
+ if (out_id || reader->index) {
+ if ((error = git_odb_hash(&id, out->ptr, out->size, GIT_OBJ_BLOB)) < 0)
+ goto done;
+ }
+
+ if (reader->index) {
+ if (!(idx_entry = git_index_get_bypath(reader->index, filename, 0)) ||
+ !git_oid_equal(&id, &idx_entry->id)) {
+ error = GIT_READER_MISMATCH;
+ goto done;
+ }
+ }
+
if (out_id)
- error = git_odb_hash(out_id, out->ptr, out->size, GIT_OBJ_BLOB);
+ git_oid_cpy(out_id, &id);
done:
git_buf_dispose(&path);
@@ -107,9 +123,13 @@ static void workdir_reader_free(git_reader *_reader)
GIT_UNUSED(_reader);
}
-int git_reader_for_workdir(git_reader **out, git_repository *repo)
+int git_reader_for_workdir(
+ git_reader **out,
+ git_repository *repo,
+ bool validate_index)
{
workdir_reader *reader;
+ int error;
assert(out && repo);
@@ -120,6 +140,12 @@ int git_reader_for_workdir(git_reader **out, git_repository *repo)
reader->reader.free = workdir_reader_free;
reader->repo = repo;
+ if (validate_index &&
+ (error = git_repository_index__weakptr(&reader->index, repo)) < 0) {
+ git__free(reader);
+ return error;
+ }
+
*out = (git_reader *)reader;
return 0;
}
@@ -183,13 +209,9 @@ int git_reader_for_index(
if (index) {
reader->index = index;
- } else {
- error = git_repository_index__weakptr(&reader->index, repo);
-
- if (error < 0) {
- git__free(reader);
- return error;
- }
+ } else if ((error = git_repository_index__weakptr(&reader->index, repo)) < 0) {
+ git__free(reader);
+ return error;
}
*out = (git_reader *)reader;
diff --git a/src/reader.h b/src/reader.h
index 7bb60e1..e1d9068 100644
--- a/src/reader.h
+++ b/src/reader.h
@@ -9,6 +9,9 @@
#include "common.h"
+/* Returned when the workdir does not match the index */
+#define GIT_READER_MISMATCH 1
+
typedef struct git_reader git_reader;
/*
@@ -76,7 +79,8 @@ extern int git_reader_for_index(
*/
extern int git_reader_for_workdir(
git_reader **out,
- git_repository *repo);
+ git_repository *repo,
+ bool validate_index);
/**
* Read the given filename from the reader and populate the given buffer