Commit 0bf672343b9f6592106ca8b4299187f497eb2b66

Edward Thomson 2022-01-05T09:30:27

Merge pull request #6158 from arroz/feat/statusRenameThreshold Add `rename_threshold` to `git_status_options`.

diff --git a/include/git2/status.h b/include/git2/status.h
index 526df63..d8f9663 100644
--- a/include/git2/status.h
+++ b/include/git2/status.h
@@ -250,6 +250,12 @@ typedef struct {
 	 * working directory and index; defaults to HEAD.
 	 */
 	git_tree          *baseline;
+
+	/**
+	 * Threshold above which similar files will be considered renames.
+	 * This is equivalent to the -M option. Defaults to 50.
+	 */
+	uint16_t          rename_threshold;
 } git_status_options;
 
 #define GIT_STATUS_OPTIONS_VERSION 1
diff --git a/src/status.c b/src/status.c
index c985646..b321e0e 100644
--- a/src/status.c
+++ b/src/status.c
@@ -336,6 +336,9 @@ int git_status_list_new(
 			GIT_DIFF_FIND_RENAMES_FROM_REWRITES |
 			GIT_DIFF_BREAK_REWRITES_FOR_RENAMES_ONLY;
 
+	if (opts != NULL && opts->rename_threshold != 0)
+		findopt.rename_threshold = opts->rename_threshold;
+
 	if (show != GIT_STATUS_SHOW_WORKDIR_ONLY) {
 		if ((error = git_diff_tree_to_index(
 				&status->head2idx, repo, head, index, &diffopt)) < 0)
diff --git a/tests/status/renames.c b/tests/status/renames.c
index e69dbcc..d17a94c 100644
--- a/tests/status/renames.c
+++ b/tests/status/renames.c
@@ -718,3 +718,66 @@ void test_status_renames__precomposed_unicode_toggle_is_rename(void)
 #endif
 }
 
+void test_status_renames__rename_threshold(void)
+{
+	git_index *index;
+	git_status_list *statuslist;
+	git_status_options opts = GIT_STATUS_OPTIONS_INIT;
+	
+	_rename_helper(g_repo, "ikeepsix.txt", "newname.txt",
+		"Line 1\n" \
+		"Line 2\n" \
+		"Line 3\n" \
+		"Line 4\n" \
+		"Line 5\n" \
+		"Line 6\n" \
+		"Line 7\n" \
+		"Line 8\n" \
+		"Line 9\n"
+	);
+	
+	opts.flags |= GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR;
+	opts.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED;
+	
+	cl_git_pass(git_repository_index(&index, g_repo));
+	
+	// Default threshold
+	{
+		struct status_entry expected[] = {
+			{ GIT_STATUS_WT_RENAMED | GIT_STATUS_WT_MODIFIED, "ikeepsix.txt", "newname.txt" },
+		};
+		
+		cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts));
+		check_status(statuslist, expected, 1);
+		git_status_list_free(statuslist);
+	}
+	
+	// Threshold set to 90
+	{
+		struct status_entry expected[] = {
+			{ GIT_STATUS_WT_DELETED, "ikeepsix.txt", NULL },
+			{ GIT_STATUS_WT_NEW, "newname.txt", NULL }
+		};
+		
+		opts.rename_threshold = 90;
+		
+		cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts));
+		check_status(statuslist, expected, 2);
+		git_status_list_free(statuslist);
+	}
+	
+	// Threshold set to 25
+	{
+		struct status_entry expected[] = {
+			{ GIT_STATUS_WT_RENAMED | GIT_STATUS_WT_MODIFIED, "ikeepsix.txt", "newname.txt" },
+		};
+		
+		opts.rename_threshold = 25;
+		
+		cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts));
+		check_status(statuslist, expected, 1);
+		git_status_list_free(statuslist);
+	}
+	
+	git_index_free(index);
+}