summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@edwardthomson.com>2018-07-01 15:13:50 +0100
committerEdward Thomson <ethomson@edwardthomson.com>2018-11-05 15:53:34 +0000
commit0f4b2f028ab3a70b76b9bd67f073747df7078559 (patch)
tree89098564ae5bac37226d8504932b059e374d49ef
parent3b674660fe3f7c05359110007099ddf051caca7d (diff)
downloadlibgit2-0f4b2f028ab3a70b76b9bd67f073747df7078559.tar.gz
reader: optionally validate index matches workdir
When using a workdir reader, optionally validate that the index contents match the working directory contents.
-rw-r--r--src/apply.c2
-rw-r--r--src/reader.c40
-rw-r--r--src/reader.h6
3 files changed, 37 insertions, 11 deletions
diff --git a/src/apply.c b/src/apply.c
index 0810c021c..d4c7dd0db 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 32900dfab..94faff701 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 7bb60e144..e1d906807 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