Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/libgit2.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/git2/diff.h2
-rw-r--r--src/diff.h2
-rw-r--r--src/diff_tform.c33
-rw-r--r--tests-clar/diff/diff_helpers.c5
-rw-r--r--tests-clar/diff/diff_helpers.h2
-rw-r--r--tests-clar/diff/rename.c119
6 files changed, 139 insertions, 24 deletions
diff --git a/include/git2/diff.h b/include/git2/diff.h
index 6939f6a2e..0d4875b43 100644
--- a/include/git2/diff.h
+++ b/include/git2/diff.h
@@ -484,7 +484,7 @@ typedef struct {
unsigned int version;
/** Combination of git_diff_find_t values (default FIND_RENAMES) */
- unsigned int flags;
+ uint32_t flags;
/** Similarity to consider a file renamed (default 50) */
uint16_t rename_threshold;
diff --git a/src/diff.h b/src/diff.h
index a9a543ecd..ac8ab2aed 100644
--- a/src/diff.h
+++ b/src/diff.h
@@ -44,6 +44,8 @@ enum {
#define GIT_DIFF_FLAG__CLEAR_INTERNAL(F) (F) = ((F) & 0x00FFFF)
+#define GIT_DIFF__VERBOSE (1 << 30)
+
struct git_diff_list {
git_refcount rc;
git_repository *repo;
diff --git a/src/diff_tform.c b/src/diff_tform.c
index b481e64ce..0f4ecc7b5 100644
--- a/src/diff_tform.c
+++ b/src/diff_tform.c
@@ -828,22 +828,37 @@ int git_diff_find_similar(
if (similarity < (int)opts.rename_from_rewrite_threshold)
continue;
- memcpy(&swap, &from->new_file, sizeof(swap));
+ memcpy(&swap, &to->new_file, sizeof(swap));
- from->status = GIT_DELTA_RENAMED;
- from->similarity = (uint32_t)similarity;
- memcpy(&from->new_file, &to->new_file, sizeof(from->new_file));
- if ((from->flags & GIT_DIFF_FLAG__TO_SPLIT) != 0) {
- from->flags &= ~GIT_DIFF_FLAG__TO_SPLIT;
+ to->status = GIT_DELTA_RENAMED;
+ to->similarity = (uint32_t)similarity;
+ memcpy(&to->new_file, &from->new_file, sizeof(to->new_file));
+ if ((to->flags & GIT_DIFF_FLAG__TO_SPLIT) != 0) {
+ to->flags &= ~GIT_DIFF_FLAG__TO_SPLIT;
num_rewrites--;
}
- memcpy(&to->new_file, &swap, sizeof(to->new_file));
- if ((to->flags & GIT_DIFF_FLAG__TO_SPLIT) == 0) {
- to->flags |= GIT_DIFF_FLAG__TO_SPLIT;
+ memcpy(&from->new_file, &swap, sizeof(from->new_file));
+ if ((from->flags & GIT_DIFF_FLAG__TO_SPLIT) == 0) {
+ from->flags |= GIT_DIFF_FLAG__TO_SPLIT;
num_rewrites++;
}
+ /* in the off chance that we've just swapped the new
+ * element into the correct place, clear the SPLIT flag
+ */
+ if (matches[matches[i].idx].idx == i &&
+ matches[matches[i].idx].similarity >
+ opts.rename_from_rewrite_threshold) {
+
+ from->status = GIT_DELTA_RENAMED;
+ from->similarity =
+ (uint32_t)matches[matches[i].idx].similarity;
+ matches[matches[i].idx].similarity = 0;
+ from->flags &= ~GIT_DIFF_FLAG__TO_SPLIT;
+ num_rewrites--;
+ }
+
num_updates++;
}
}
diff --git a/tests-clar/diff/diff_helpers.c b/tests-clar/diff/diff_helpers.c
index 75eda0520..4e23792a6 100644
--- a/tests-clar/diff/diff_helpers.c
+++ b/tests-clar/diff/diff_helpers.c
@@ -213,3 +213,8 @@ void diff_print(FILE *fp, git_diff_list *diff)
{
cl_git_pass(git_diff_print_patch(diff, diff_print_cb, fp ? fp : stderr));
}
+
+void diff_print_raw(FILE *fp, git_diff_list *diff)
+{
+ cl_git_pass(git_diff_print_raw(diff, diff_print_cb, fp ? fp : stderr));
+}
diff --git a/tests-clar/diff/diff_helpers.h b/tests-clar/diff/diff_helpers.h
index b39a69d1d..bb76d0076 100644
--- a/tests-clar/diff/diff_helpers.h
+++ b/tests-clar/diff/diff_helpers.h
@@ -65,4 +65,4 @@ extern int diff_foreach_via_iterator(
void *data);
extern void diff_print(FILE *fp, git_diff_list *diff);
-
+extern void diff_print_raw(FILE *fp, git_diff_list *diff);
diff --git a/tests-clar/diff/rename.c b/tests-clar/diff/rename.c
index b4f9df713..1edf66e95 100644
--- a/tests-clar/diff/rename.c
+++ b/tests-clar/diff/rename.c
@@ -15,18 +15,6 @@ void test_diff_rename__cleanup(void)
}
/*
-static int debug_print(
- const git_diff_delta *delta, const git_diff_range *range, char usage,
- const char *line, size_t line_len, void *data)
-{
- GIT_UNUSED(delta); GIT_UNUSED(range); GIT_UNUSED(usage);
- GIT_UNUSED(line_len); GIT_UNUSED(data);
- fputs(line, stderr);
- return 0;
-}
-*/
-
-/*
* Renames repo has:
*
* commit 31e47d8c1fa36d7f8d537b96158e3f024de0a9f2 -
@@ -539,7 +527,7 @@ void test_diff_rename__working_directory_changes(void)
/*
fprintf(stderr, "\n\n");
- cl_git_pass(git_diff_print_raw(diff, debug_print, NULL));
+ diff_print_raw(stderr, diff);
*/
memset(&exp, 0, sizeof(exp));
@@ -613,3 +601,108 @@ void test_diff_rename__patch(void)
git_tree_free(old_tree);
git_tree_free(new_tree);
}
+
+void test_diff_rename__file_exchange(void)
+{
+ git_buf c1 = GIT_BUF_INIT, c2 = GIT_BUF_INIT;
+ git_index *index;
+ git_tree *tree;
+ git_diff_list *diff;
+ git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT;
+ git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT;
+ diff_expects exp;
+
+ cl_git_pass(git_futils_readbuffer(&c1, "renames/untimely.txt"));
+ cl_git_pass(git_futils_readbuffer(&c2, "renames/songof7cities.txt"));
+ cl_git_pass(git_futils_writebuffer(&c1, "renames/songof7cities.txt", 0, 0));
+ cl_git_pass(git_futils_writebuffer(&c2, "renames/untimely.txt", 0, 0));
+
+ cl_git_pass(
+ git_revparse_single((git_object **)&tree, g_repo, "HEAD^{tree}"));
+
+ cl_git_pass(git_repository_index(&index, g_repo));
+ cl_git_pass(git_index_read_tree(index, tree));
+ cl_git_pass(git_index_add_bypath(index, "songof7cities.txt"));
+ cl_git_pass(git_index_add_bypath(index, "untimely.txt"));
+
+ cl_git_pass(git_diff_tree_to_index(&diff, g_repo, tree, index, &diffopts));
+
+ memset(&exp, 0, sizeof(exp));
+ cl_git_pass(git_diff_foreach(
+ diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ cl_assert_equal_i(2, exp.files);
+ cl_assert_equal_i(2, exp.file_status[GIT_DELTA_MODIFIED]);
+
+ opts.flags = GIT_DIFF_FIND_ALL;
+ cl_git_pass(git_diff_find_similar(diff, &opts));
+
+ memset(&exp, 0, sizeof(exp));
+ cl_git_pass(git_diff_foreach(
+ diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ cl_assert_equal_i(2, exp.files);
+ cl_assert_equal_i(2, exp.file_status[GIT_DELTA_RENAMED]);
+
+ git_diff_list_free(diff);
+ git_tree_free(tree);
+ git_index_free(index);
+
+ git_buf_free(&c1);
+ git_buf_free(&c2);
+}
+
+void test_diff_rename__file_split(void)
+{
+ git_buf c1 = GIT_BUF_INIT, c2 = GIT_BUF_INIT;
+ git_index *index;
+ git_tree *tree;
+ git_diff_list *diff;
+ git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT;
+ git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT;
+ diff_expects exp;
+
+ /* put the first 2/3 of file into one new place
+ * and the second 2/3 of file into another new place
+ */
+ cl_git_pass(git_futils_readbuffer(&c1, "renames/songof7cities.txt"));
+ cl_git_pass(git_buf_set(&c2, c1.ptr, c1.size));
+ git_buf_truncate(&c1, c1.size * 2 / 3);
+ git_buf_consume(&c2, ((char *)c2.ptr) + (c2.size / 3));
+ cl_git_pass(git_futils_writebuffer(&c1, "renames/song_a.txt", 0, 0));
+ cl_git_pass(git_futils_writebuffer(&c2, "renames/song_b.txt", 0, 0));
+
+ cl_git_pass(
+ git_revparse_single((git_object **)&tree, g_repo, "HEAD^{tree}"));
+
+ cl_git_pass(git_repository_index(&index, g_repo));
+ cl_git_pass(git_index_read_tree(index, tree));
+ cl_git_pass(git_index_add_bypath(index, "song_a.txt"));
+ cl_git_pass(git_index_add_bypath(index, "song_b.txt"));
+
+ diffopts.flags = GIT_DIFF_INCLUDE_UNMODIFIED;
+
+ cl_git_pass(git_diff_tree_to_index(&diff, g_repo, tree, index, &diffopts));
+
+ memset(&exp, 0, sizeof(exp));
+ cl_git_pass(git_diff_foreach(
+ diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ cl_assert_equal_i(6, exp.files);
+ cl_assert_equal_i(2, exp.file_status[GIT_DELTA_ADDED]);
+ cl_assert_equal_i(4, exp.file_status[GIT_DELTA_UNMODIFIED]);
+
+ opts.flags = GIT_DIFF_FIND_ALL;
+ cl_git_pass(git_diff_find_similar(diff, &opts));
+
+ memset(&exp, 0, sizeof(exp));
+ cl_git_pass(git_diff_foreach(
+ diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ cl_assert_equal_i(6, exp.files);
+ cl_assert_equal_i(2, exp.file_status[GIT_DELTA_COPIED]);
+ cl_assert_equal_i(4, exp.file_status[GIT_DELTA_UNMODIFIED]);
+
+ git_diff_list_free(diff);
+ git_tree_free(tree);
+ git_index_free(index);
+
+ git_buf_free(&c1);
+ git_buf_free(&c2);
+}