diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/diff.c | 77 | ||||
-rw-r--r-- | src/status.c | 29 |
2 files changed, 62 insertions, 44 deletions
diff --git a/src/diff.c b/src/diff.c index e875d09b3..77dbbd8bc 100644 --- a/src/diff.c +++ b/src/diff.c @@ -258,6 +258,26 @@ int git_diff_delta__casecmp(const void *a, const void *b) return val ? val : ((int)da->status - (int)db->status); } +GIT_INLINE(const char *) diff_delta__i2w_path(const git_diff_delta *delta) +{ + return delta->old_file.path ? + delta->old_file.path : delta->new_file.path; +} + +int git_diff_delta__i2w_cmp(const void *a, const void *b) +{ + const git_diff_delta *da = a, *db = b; + int val = strcmp(diff_delta__i2w_path(da), diff_delta__i2w_path(db)); + return val ? val : ((int)da->status - (int)db->status); +} + +int git_diff_delta__i2w_casecmp(const void *a, const void *b) +{ + const git_diff_delta *da = a, *db = b; + int val = strcasecmp(diff_delta__i2w_path(da), diff_delta__i2w_path(db)); + return val ? val : ((int)da->status - (int)db->status); +} + bool git_diff_delta__should_skip( const git_diff_options *opts, const git_diff_delta *delta) { @@ -1276,7 +1296,7 @@ int git_diff__paired_foreach( git_diff_delta *h2i, *i2w; size_t i, j, i_max, j_max; int (*strcomp)(const char *, const char *) = git__strcmp; - bool icase_mismatch; + bool h2i_icase, i2w_icase, icase_mismatch; i_max = head2idx ? head2idx->deltas.length : 0; j_max = idx2wd ? idx2wd->deltas.length : 0; @@ -1291,24 +1311,35 @@ int git_diff__paired_foreach( * Therefore the main thing we need to do here is make sure the diffs * are traversed in a compatible order. To do this, we temporarily * resort a mismatched diff to get the order correct. + * + * In order to traverse renames in the index->workdir, we need to + * ensure that we compare the index name on both sides, so we + * always sort by the old name in the i2w list. */ + h2i_icase = head2idx != NULL && + (head2idx->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) != 0; + + i2w_icase = idx2wd != NULL && + (idx2wd->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) != 0; + icase_mismatch = - (head2idx != NULL && idx2wd != NULL && - ((head2idx->opts.flags ^ idx2wd->opts.flags) & GIT_DIFF_DELTAS_ARE_ICASE)); - - /* force case-sensitive delta sort */ - if (icase_mismatch) { - if (head2idx->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) { - git_vector_set_cmp(&head2idx->deltas, git_diff_delta__cmp); - git_vector_sort(&head2idx->deltas); - } else { - git_vector_set_cmp(&idx2wd->deltas, git_diff_delta__cmp); - git_vector_sort(&idx2wd->deltas); - } + (head2idx != NULL && idx2wd != NULL && h2i_icase != i2w_icase); + + if (icase_mismatch && h2i_icase) { + git_vector_set_cmp(&head2idx->deltas, git_diff_delta__cmp); + git_vector_sort(&head2idx->deltas); } - else if (head2idx != NULL && head2idx->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) + + if (i2w_icase && !icase_mismatch) { strcomp = git__strcasecmp; + git_vector_set_cmp(&idx2wd->deltas, git_diff_delta__i2w_casecmp); + git_vector_sort(&idx2wd->deltas); + } else if (idx2wd != NULL) { + git_vector_set_cmp(&idx2wd->deltas, git_diff_delta__i2w_cmp); + git_vector_sort(&idx2wd->deltas); + } + for (i = 0, j = 0; i < i_max || j < j_max; ) { h2i = head2idx ? GIT_VECTOR_GET(&head2idx->deltas, i) : NULL; i2w = idx2wd ? GIT_VECTOR_GET(&idx2wd->deltas, j) : NULL; @@ -1332,14 +1363,16 @@ int git_diff__paired_foreach( } /* restore case-insensitive delta sort */ - if (icase_mismatch) { - if (head2idx->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) { - git_vector_set_cmp(&head2idx->deltas, git_diff_delta__casecmp); - git_vector_sort(&head2idx->deltas); - } else { - git_vector_set_cmp(&idx2wd->deltas, git_diff_delta__casecmp); - git_vector_sort(&idx2wd->deltas); - } + if (icase_mismatch && h2i_icase) { + git_vector_set_cmp(&head2idx->deltas, git_diff_delta__casecmp); + git_vector_sort(&head2idx->deltas); + } + + /* restore idx2wd sort by new path */ + if (idx2wd != NULL) { + git_vector_set_cmp(&idx2wd->deltas, + i2w_icase ? git_diff_delta__casecmp : git_diff_delta__cmp); + git_vector_sort(&idx2wd->deltas); } return 0; diff --git a/src/status.c b/src/status.c index ccb8d37da..b2353258b 100644 --- a/src/status.c +++ b/src/status.c @@ -225,24 +225,6 @@ static git_status_list *git_status_list_alloc(git_index *index) return status; } -/* -static int newfile_cmp(const void *a, const void *b) -{ - const git_diff_delta *delta_a = a; - const git_diff_delta *delta_b = b; - - return git__strcmp(delta_a->new_file.path, delta_b->new_file.path); -} - -static int newfile_casecmp(const void *a, const void *b) -{ - const git_diff_delta *delta_a = a; - const git_diff_delta *delta_b = b; - - return git__strcasecmp(delta_a->new_file.path, delta_b->new_file.path); -} -*/ - int git_status_list_new( git_status_list **out, git_repository *repo, @@ -251,7 +233,7 @@ int git_status_list_new( git_index *index = NULL; git_status_list *status = NULL; git_diff_options diffopt = GIT_DIFF_OPTIONS_INIT; - git_diff_find_options findopts_i2w = GIT_DIFF_FIND_OPTIONS_INIT; + git_diff_find_options findopt = GIT_DIFF_FIND_OPTIONS_INIT; git_tree *head = NULL; git_status_show_t show = opts ? opts->show : GIT_STATUS_SHOW_INDEX_AND_WORKDIR; @@ -284,6 +266,7 @@ int git_status_list_new( } diffopt.flags = GIT_DIFF_INCLUDE_TYPECHANGE; + findopt.flags = GIT_DIFF_FIND_FOR_UNTRACKED; if ((flags & GIT_STATUS_OPT_INCLUDE_UNTRACKED) != 0) diffopt.flags = diffopt.flags | GIT_DIFF_INCLUDE_UNTRACKED; @@ -300,7 +283,9 @@ int git_status_list_new( if ((flags & GIT_STATUS_OPT_EXCLUDE_SUBMODULES) != 0) diffopt.flags = diffopt.flags | GIT_DIFF_IGNORE_SUBMODULES; - findopts_i2w.flags |= GIT_DIFF_FIND_FOR_UNTRACKED; + if ((flags & GIT_STATUS_OPT_RENAMES_FROM_REWRITES) != 0) + findopt.flags = findopt.flags | GIT_DIFF_FIND_AND_BREAK_REWRITES | + GIT_DIFF_FIND_RENAMES_FROM_REWRITES; if (show != GIT_STATUS_SHOW_WORKDIR_ONLY) { if ((error = git_diff_tree_to_index( @@ -308,7 +293,7 @@ int git_status_list_new( goto done; if ((flags & GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX) != 0 && - (error = git_diff_find_similar(status->head2idx, NULL)) < 0) + (error = git_diff_find_similar(status->head2idx, &findopt)) < 0) goto done; } @@ -318,7 +303,7 @@ int git_status_list_new( goto done; if ((flags & GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR) != 0 && - (error = git_diff_find_similar(status->idx2wd, &findopts_i2w)) < 0) + (error = git_diff_find_similar(status->idx2wd, &findopt)) < 0) goto done; } |