diff --git a/include/git2/diff.h b/include/git2/diff.h index 9fcc3bb08..cac3b268a 100644 --- a/include/git2/diff.h +++ b/include/git2/diff.h @@ -124,6 +124,11 @@ typedef enum { /** Use case insensitive filename comparisons */ GIT_DIFF_IGNORE_CASE = (1u << 10), + /** May be combined with `GIT_DIFF_IGNORE_CASE` to specify that a file + * that has changed case will be returned as an add/delete pair. + */ + GIT_DIFF_INCLUDE_CASECHANGE = (1u << 11), + /** If the pathspec is set in the diff options, this flags means to * apply it as an exact match instead of as an fnmatch pattern. */ @@ -220,7 +225,7 @@ typedef struct git_diff git_diff; typedef enum { GIT_DIFF_FLAG_BINARY = (1u << 0), /**< file(s) treated as binary data */ GIT_DIFF_FLAG_NOT_BINARY = (1u << 1), /**< file(s) treated as text data */ - GIT_DIFF_FLAG_VALID_ID = (1u << 2), /**< `id` value is known correct */ + GIT_DIFF_FLAG_VALID_ID = (1u << 2), /**< `id` value is known correct */ } git_diff_flag_t; /** diff --git a/src/checkout.c b/src/checkout.c index dd10732b5..a647ce0b9 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -2485,7 +2485,8 @@ int git_checkout_iterator( GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_TYPECHANGE | GIT_DIFF_INCLUDE_TYPECHANGE_TREES | - GIT_DIFF_SKIP_BINARY_CHECK; + GIT_DIFF_SKIP_BINARY_CHECK | + GIT_DIFF_INCLUDE_CASECHANGE; if (data.opts.checkout_strategy & GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH) diff_opts.flags |= GIT_DIFF_DISABLE_PATHSPEC_MATCH; if (data.opts.paths.count > 0) diff --git a/src/diff.c b/src/diff.c index 08e218cce..f7e1c8ee4 100644 --- a/src/diff.c +++ b/src/diff.c @@ -822,6 +822,19 @@ static int maybe_modified( status = GIT_DELTA_UNMODIFIED; } + /* If we want case changes, then break this into a delete of the old + * and an add of the new so that consumers can act accordingly (eg, + * checkout will update the case on disk.) + */ + if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_IGNORE_CASE) && + DIFF_FLAG_IS_SET(diff, GIT_DIFF_INCLUDE_CASECHANGE) && + strcmp(oitem->path, nitem->path) != 0) { + + if (!(error = diff_delta__from_one(diff, GIT_DELTA_DELETED, oitem))) + error = diff_delta__from_one(diff, GIT_DELTA_ADDED, nitem); + return error; + } + return diff_delta__from_two( diff, status, oitem, omode, nitem, nmode, git_oid_iszero(&noid) ? NULL : &noid, matched_pathspec);