Commit f8275890676a56735b1af1abde859722f040a61c

Russell Belfer 2013-02-22T10:19:50

Replace static data with configured metric Instead of creating three git_diff_similarity_metric statically for the various config options, just create the metric structure on demand and populate it, using the payload to specific the extra flags that should be passed to the hashsig. This removes a level of obfuscation from the code, I think.

diff --git a/src/diff_tform.c b/src/diff_tform.c
index ae0fd36..66a4702 100644
--- a/src/diff_tform.c
+++ b/src/diff_tform.c
@@ -170,21 +170,21 @@ int git_diff_merge(
 	return error;
 }
 
-#define FIND_SIMILAR_HASHSIG(NAME,OPT) \
-	static int find_similar__hashsig_for_file ## NAME( \
-		void **out, const git_diff_file *f, const char *path, void *p) { \
-		GIT_UNUSED(f); GIT_UNUSED(p); \
-		return git_hashsig_create_fromfile((git_hashsig **)out, path, OPT); \
-	} \
-	static int find_similar__hashsig_for_buf ## NAME( \
-		void **out, const git_diff_file *f, const char *buf, size_t len, void *p) { \
-		GIT_UNUSED(f); GIT_UNUSED(p); \
-		return git_hashsig_create((git_hashsig **)out, buf, len, OPT); \
-	}
+static int find_similar__hashsig_for_file(
+	void **out, const git_diff_file *f, const char *path, void *p)
+{
+	git_hashsig_option_t opt = (git_hashsig_option_t)p;
+	GIT_UNUSED(f);
+	return git_hashsig_create_fromfile((git_hashsig **)out, path, opt);
+}
 
-FIND_SIMILAR_HASHSIG(_default, GIT_HASHSIG_SMART_WHITESPACE);
-FIND_SIMILAR_HASHSIG(_ignore_whitespace, GIT_HASHSIG_IGNORE_WHITESPACE);
-FIND_SIMILAR_HASHSIG(_include_whitespace, GIT_HASHSIG_NORMAL);
+static int find_similar__hashsig_for_buf(
+	void **out, const git_diff_file *f, const char *buf, size_t len, void *p)
+{
+	git_hashsig_option_t opt = (git_hashsig_option_t)p;
+	GIT_UNUSED(f);
+	return git_hashsig_create((git_hashsig **)out, buf, len, opt);
+}
 
 static void find_similar__hashsig_free(void *sig, void *payload)
 {
@@ -200,30 +200,6 @@ static int find_similar__calc_similarity(
 	return 0;
 }
 
-static git_diff_similarity_metric find_similar__internal_metrics[3] = {
-	{
-		find_similar__hashsig_for_file_default,
-		find_similar__hashsig_for_buf_default,
-		find_similar__hashsig_free,
-		find_similar__calc_similarity,
-		NULL
-	},
-	{
-		find_similar__hashsig_for_file_ignore_whitespace,
-		find_similar__hashsig_for_buf_ignore_whitespace,
-		find_similar__hashsig_free,
-		find_similar__calc_similarity,
-		NULL
-	},
-	{
-		find_similar__hashsig_for_file_include_whitespace,
-		find_similar__hashsig_for_buf_include_whitespace,
-		find_similar__hashsig_free,
-		find_similar__calc_similarity,
-		NULL
-	}
-};
-
 #define DEFAULT_THRESHOLD 50
 #define DEFAULT_BREAK_REWRITE_THRESHOLD 60
 #define DEFAULT_TARGET_LIMIT 200
@@ -292,14 +268,22 @@ static int normalize_find_opts(
 			opts->target_limit = limit;
 	}
 
-	/* for now, always assign the same internal metric */
+	/* assign the internal metric with whitespace flag as payload */
 	if (!opts->metric) {
+		opts->metric = git__malloc(sizeof(git_diff_similarity_metric));
+		GITERR_CHECK_ALLOC(opts->metric);
+
+		opts->metric->file_signature = find_similar__hashsig_for_file;
+		opts->metric->buffer_signature = find_similar__hashsig_for_buf;
+		opts->metric->free_signature = find_similar__hashsig_free;
+		opts->metric->similarity = find_similar__calc_similarity;
+
 		if (opts->flags & GIT_DIFF_FIND_IGNORE_WHITESPACE)
-			opts->metric = &find_similar__internal_metrics[1];
+			opts->metric->payload = (void *)GIT_HASHSIG_IGNORE_WHITESPACE;
 		else if (opts->flags & GIT_DIFF_FIND_DONT_IGNORE_WHITESPACE)
-			opts->metric = &find_similar__internal_metrics[2];
+			opts->metric->payload = (void *)GIT_HASHSIG_NORMAL;
 		else
-			opts->metric = &find_similar__internal_metrics[0];
+			opts->metric->payload = (void *)GIT_HASHSIG_SMART_WHITESPACE;
 	}
 
 	return 0;
@@ -667,6 +651,9 @@ cleanup:
 	}
 	git__free(cache);
 
+	if (!given_opts || !given_opts->metric)
+		git__free(opts.metric);
+
 	return error;
 }