diff options
-rw-r--r-- | deps/ntlmclient/crypt_openssl.c | 2 | ||||
-rw-r--r-- | include/git2/status.h | 6 | ||||
-rw-r--r-- | src/config_file.c | 17 | ||||
-rw-r--r-- | src/diff_tform.c | 2 | ||||
-rw-r--r-- | src/status.c | 3 | ||||
-rw-r--r-- | tests/config/conditionals.c | 25 | ||||
-rw-r--r-- | tests/resources/renames/.gitted/objects/41/a766bb079e18ff6a24571831bd751168799a02 | 1 | ||||
-rw-r--r-- | tests/resources/renames/.gitted/objects/ba/8b004914491b129b4feff51b5fd8553b8e8156 | bin | 0 -> 191 bytes | |||
-rw-r--r-- | tests/resources/renames/.gitted/objects/e5/6d39ca6d946331aa79c9c443d46c8a6ed4f550 | bin | 0 -> 36 bytes | |||
-rw-r--r-- | tests/resources/renames/.gitted/refs/heads/case-insensitive-status | 1 | ||||
-rw-r--r-- | tests/status/renames.c | 124 |
11 files changed, 176 insertions, 5 deletions
diff --git a/deps/ntlmclient/crypt_openssl.c b/deps/ntlmclient/crypt_openssl.c index 463eae4f8..bab8276ac 100644 --- a/deps/ntlmclient/crypt_openssl.c +++ b/deps/ntlmclient/crypt_openssl.c @@ -44,7 +44,7 @@ static inline void HMAC_CTX_free(HMAC_CTX *ctx) #endif -#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(CRYPT_OPENSSL_DYNAMIC) +#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !LIBRESSL_VERSION_NUMBER) || defined(CRYPT_OPENSSL_DYNAMIC) static inline void HMAC_CTX_cleanup(HMAC_CTX *ctx) { diff --git a/include/git2/status.h b/include/git2/status.h index 526df6399..d8f9663b4 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/config_file.c b/src/config_file.c index 11b444094..43a6ba440 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -724,14 +724,25 @@ static const struct { static int parse_conditional_include(config_file_parse_data *parse_data, const char *section, const char *file) { char *condition; - size_t i; + size_t section_len, i; int error = 0, matches; if (!parse_data->repo || !file) return 0; - condition = git__substrdup(section + strlen("includeIf."), - strlen(section) - strlen("includeIf.") - strlen(".path")); + section_len = strlen(section); + + /* + * We checked that the string starts with `includeIf.` and ends + * in `.path` to get here. Make sure it consists of more. + */ + if (section_len < CONST_STRLEN("includeIf.") + CONST_STRLEN(".path")) + return 0; + + condition = git__substrdup(section + CONST_STRLEN("includeIf."), + section_len - CONST_STRLEN("includeIf.") - CONST_STRLEN(".path")); + + GIT_ERROR_CHECK_ALLOC(condition); for (i = 0; i < ARRAY_SIZE(conditions); i++) { if (git__prefixcmp(condition, conditions[i].prefix)) diff --git a/src/diff_tform.c b/src/diff_tform.c index d14134071..f9836d245 100644 --- a/src/diff_tform.c +++ b/src/diff_tform.c @@ -375,7 +375,7 @@ static int apply_splits_and_deletes( size_t i; git_diff_delta *delta; - if (git_vector_init(&onto, expected_size, git_diff_delta__cmp) < 0) + if (git_vector_init(&onto, expected_size, diff->deltas._cmp) < 0) return -1; /* build new delta list without TO_DELETE and splitting TO_SPLIT */ diff --git a/src/status.c b/src/status.c index c98564643..b321e0efb 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/config/conditionals.c b/tests/config/conditionals.c index 6249dbd79..564719dcb 100644 --- a/tests/config/conditionals.c +++ b/tests/config/conditionals.c @@ -148,3 +148,28 @@ void test_config_conditionals__onbranch(void) assert_condition_includes("onbranch", "dir*", false); assert_condition_includes("onbranch", "dir/*", false); } + +void test_config_conditionals__empty(void) +{ + git_buf value = GIT_BUF_INIT; + git_str buf = GIT_STR_INIT; + git_config *cfg; + + cl_git_pass(git_str_puts(&buf, "[includeIf]\n")); + cl_git_pass(git_str_puts(&buf, "path = other\n")); + + cl_git_mkfile("empty_standard_repo/.git/config", buf.ptr); + cl_git_mkfile("empty_standard_repo/.git/other", "[foo]\nbar=baz\n"); + _repo = cl_git_sandbox_reopen(); + + git_str_dispose(&buf); + + cl_git_pass(git_repository_config(&cfg, _repo)); + + cl_git_fail_with(GIT_ENOTFOUND, + git_config_get_string_buf(&value, cfg, "foo.bar")); + + git_str_dispose(&buf); + git_buf_dispose(&value); + git_config_free(cfg); +} diff --git a/tests/resources/renames/.gitted/objects/41/a766bb079e18ff6a24571831bd751168799a02 b/tests/resources/renames/.gitted/objects/41/a766bb079e18ff6a24571831bd751168799a02 new file mode 100644 index 000000000..4bd7592d5 --- /dev/null +++ b/tests/resources/renames/.gitted/objects/41/a766bb079e18ff6a24571831bd751168799a02 @@ -0,0 +1 @@ +xKN0DYGD#!CK=8pzZ[ԫ{`g4:3`N?E Bp8=wL, `ubΜh#VSᣬop}%smǃc}2nNKDo%xE'I׃kO]J]A0 ƃ ZʟƆ_[
\ No newline at end of file diff --git a/tests/resources/renames/.gitted/objects/ba/8b004914491b129b4feff51b5fd8553b8e8156 b/tests/resources/renames/.gitted/objects/ba/8b004914491b129b4feff51b5fd8553b8e8156 Binary files differnew file mode 100644 index 000000000..c61d650ce --- /dev/null +++ b/tests/resources/renames/.gitted/objects/ba/8b004914491b129b4feff51b5fd8553b8e8156 diff --git a/tests/resources/renames/.gitted/objects/e5/6d39ca6d946331aa79c9c443d46c8a6ed4f550 b/tests/resources/renames/.gitted/objects/e5/6d39ca6d946331aa79c9c443d46c8a6ed4f550 Binary files differnew file mode 100644 index 000000000..d6deb188d --- /dev/null +++ b/tests/resources/renames/.gitted/objects/e5/6d39ca6d946331aa79c9c443d46c8a6ed4f550 diff --git a/tests/resources/renames/.gitted/refs/heads/case-insensitive-status b/tests/resources/renames/.gitted/refs/heads/case-insensitive-status new file mode 100644 index 000000000..5a92127e7 --- /dev/null +++ b/tests/resources/renames/.gitted/refs/heads/case-insensitive-status @@ -0,0 +1 @@ +41a766bb079e18ff6a24571831bd751168799a02 diff --git a/tests/status/renames.c b/tests/status/renames.c index e69dbcce0..d5cf87d07 100644 --- a/tests/status/renames.c +++ b/tests/status/renames.c @@ -718,3 +718,127 @@ 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); +} + +void test_status_renames__case_insensitive_h2i_and_i2wc(void) +{ + git_status_list *statuslist; + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + git_reference *head, *test_branch; + git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; + git_str path_to_delete = GIT_STR_INIT; + git_str path_to_edit = GIT_STR_INIT; + git_index *index; + git_strarray paths = { NULL, 0 }; + + struct status_entry expected[] = { + { GIT_STATUS_INDEX_RENAMED | GIT_STATUS_WT_MODIFIED, "sixserving.txt", "sixserving-renamed.txt" }, + { GIT_STATUS_INDEX_DELETED, "Wow.txt", "Wow.txt" } + }; + + + /* Checkout the correct branch */ + checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE; + cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD")); + cl_git_pass(git_reference_symbolic_set_target( + &test_branch, head, "refs/heads/case-insensitive-status", NULL)); + cl_git_pass(git_checkout_head(g_repo, &checkout_opts)); + + cl_git_pass(git_repository_index(&index, g_repo)); + + + /* Rename sixserving.txt, delete Wow.txt, and stage those changes */ + rename_file(g_repo, "sixserving.txt", "sixserving-renamed.txt"); + cl_git_pass(git_str_joinpath( + &path_to_delete, git_repository_workdir(g_repo), "Wow.txt")); + cl_git_rmfile(path_to_delete.ptr); + + cl_git_pass(git_index_add_all(index, &paths, GIT_INDEX_ADD_FORCE, NULL, NULL)); + cl_git_pass(git_index_write(index)); + + + /* Change content of sixserving-renamed.txt */ + cl_git_pass(git_str_joinpath( + &path_to_edit, git_repository_workdir(g_repo), "sixserving-renamed.txt")); + cl_git_append2file(path_to_edit.ptr, "New content\n"); + + /* Run status */ + opts.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED; + opts.flags |= GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR; + opts.flags |= GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX; + opts.flags |= GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY; + + cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); + check_status(statuslist, expected, 2); + git_status_list_free(statuslist); + + git_index_free(index); + + git_str_dispose(&path_to_delete); + git_str_dispose(&path_to_edit); + + git_reference_free(head); + git_reference_free(test_branch); +} |