Commit 399c0b194045be1a7f6440347ce3e08ffc1b8584

Edward Thomson 2018-01-03T14:55:06

Merge pull request #4462 from pks-t/pks/diff-generated-excessive-stats diff_generate: avoid excessive stats of .gitattribute files

diff --git a/src/diff.h b/src/diff.h
index 4e5dd93..8c04438 100644
--- a/src/diff.h
+++ b/src/diff.h
@@ -34,6 +34,7 @@ typedef enum {
 struct git_diff {
 	git_refcount     rc;
 	git_repository   *repo;
+	git_attr_session attrsession;
 	git_diff_origin_t type;
 	git_diff_options opts;
 	git_vector       deltas;    /* vector of git_diff_delta */
diff --git a/src/diff_driver.c b/src/diff_driver.c
index 8cd57cd..7114b06 100644
--- a/src/diff_driver.c
+++ b/src/diff_driver.c
@@ -354,27 +354,30 @@ done:
 }
 
 int git_diff_driver_lookup(
-	git_diff_driver **out, git_repository *repo, const char *path)
+	git_diff_driver **out, git_repository *repo,
+	git_attr_session *attrsession, const char *path)
 {
 	int error = 0;
-	const char *value;
+	const char *values[1], *attrs[] = { "diff" };
 
 	assert(out);
 	*out = NULL;
 
 	if (!repo || !path || !strlen(path))
 		/* just use the auto value */;
-	else if ((error = git_attr_get(&value, repo, 0, path, "diff")) < 0)
+	else if ((error = git_attr_get_many_with_session(values, repo,
+			attrsession, 0, path, 1, attrs)) < 0)
 		/* return error below */;
-	else if (GIT_ATTR_UNSPECIFIED(value))
+
+	else if (GIT_ATTR_UNSPECIFIED(values[0]))
 		/* just use the auto value */;
-	else if (GIT_ATTR_FALSE(value))
+	else if (GIT_ATTR_FALSE(values[0]))
 		*out = &global_drivers[DIFF_DRIVER_BINARY];
-	else if (GIT_ATTR_TRUE(value))
+	else if (GIT_ATTR_TRUE(values[0]))
 		*out = &global_drivers[DIFF_DRIVER_TEXT];
 
 	/* otherwise look for driver information in config and build driver */
-	else if ((error = git_diff_driver_load(out, repo, value)) < 0) {
+	else if ((error = git_diff_driver_load(out, repo, values[0])) < 0) {
 		if (error == GIT_ENOTFOUND) {
 			error = 0;
 			giterr_clear();
diff --git a/src/diff_driver.h b/src/diff_driver.h
index 5691cac..a03a67e 100644
--- a/src/diff_driver.h
+++ b/src/diff_driver.h
@@ -9,6 +9,7 @@
 
 #include "common.h"
 
+#include "attr_file.h"
 #include "buffer.h"
 
 typedef struct git_diff_driver_registry git_diff_driver_registry;
@@ -18,7 +19,8 @@ void git_diff_driver_registry_free(git_diff_driver_registry *);
 
 typedef struct git_diff_driver git_diff_driver;
 
-int git_diff_driver_lookup(git_diff_driver **, git_repository *, const char *);
+int git_diff_driver_lookup(git_diff_driver **, git_repository *,
+	git_attr_session *attrsession, const char *);
 void git_diff_driver_free(git_diff_driver *);
 
 /* diff option flags to force off and on for this driver */
diff --git a/src/diff_file.c b/src/diff_file.c
index 0813315..5bb9c37 100644
--- a/src/diff_file.c
+++ b/src/diff_file.c
@@ -54,7 +54,8 @@ static int diff_file_content_init_common(
 		fc->src = GIT_ITERATOR_TYPE_TREE;
 
 	if (!fc->driver &&
-		git_diff_driver_lookup(&fc->driver, fc->repo, fc->file->path) < 0)
+		git_diff_driver_lookup(&fc->driver, fc->repo,
+		    NULL, fc->file->path) < 0)
 		return -1;
 
 	/* give driver a chance to modify options */
@@ -101,7 +102,8 @@ int git_diff_file_content__init_from_diff(
 	fc->file = use_old ? &delta->old_file : &delta->new_file;
 	fc->src  = use_old ? diff->old_src : diff->new_src;
 
-	if (git_diff_driver_lookup(&fc->driver, fc->repo, fc->file->path) < 0)
+	if (git_diff_driver_lookup(&fc->driver, fc->repo,
+		    &diff->attrsession, fc->file->path) < 0)
 		return -1;
 
 	switch (delta->status) {
diff --git a/src/diff_generate.c b/src/diff_generate.c
index bce2a68..e11cbe4 100644
--- a/src/diff_generate.c
+++ b/src/diff_generate.c
@@ -389,6 +389,7 @@ static void diff_generated_free(git_diff *d)
 {
 	git_diff_generated *diff = (git_diff_generated *)d;
 
+	git_attr_session__free(&diff->base.attrsession);
 	git_vector_free_deep(&diff->base.deltas);
 
 	git_pathspec__vfree(&diff->pathspec);
@@ -418,6 +419,7 @@ static git_diff_generated *diff_generated_alloc(
 	diff->base.new_src = new_iter->type;
 	diff->base.patch_fn = git_patch_generated_from_diff;
 	diff->base.free_fn = diff_generated_free;
+	git_attr_session__init(&diff->base.attrsession, repo);
 	memcpy(&diff->base.opts, &dflt, sizeof(git_diff_options));
 
 	git_pool_init(&diff->base.pool, 1);