Scenario: A file is stored in the repository using LF line endings and checked out in the working tree with LF line endings. If the working tree file then has its line endings changed to CRLF, a force checkout of the file does not replace the content, and the file remains modified.
Here is a test point that fails:
void test_checkout_crlf__filtered_working_tree_file_equals_target(void)
{
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
opts.checkout_strategy = GIT_CHECKOUT_FORCE;
cl_git_mkfile("./crlf/.gitattributes", "* text=auto\n");
if (GIT_EOL_NATIVE == GIT_EOL_CRLF) {
cl_git_mkfile("./crlf/all-lf", ALL_LF_TEXT_AS_LF);
cl_git_mkfile("./crlf/all-crlf", ALL_CRLF_TEXT_AS_LF);
} else {
cl_git_mkfile("./crlf/all-lf", ALL_LF_TEXT_AS_CRLF);
cl_git_mkfile("./crlf/all-crlf", ALL_CRLF_TEXT_AS_LF);
}
cl_git_pass(git_checkout_head(g_repo, &opts));
if (GIT_EOL_NATIVE == GIT_EOL_CRLF) {
check_file_contents("./crlf/all-lf", ALL_LF_TEXT_AS_CRLF);
check_file_contents("./crlf/all-crlf", ALL_CRLF_TEXT_AS_CRLF);
} else {
check_file_contents("./crlf/all-lf", ALL_LF_TEXT_RAW);
check_file_contents("./crlf/all-crlf", ALL_CRLF_TEXT_RAW);
}
}
I debugged this and found that checkout_is_workdir_modified compares the base/target oid with the FILTERED oid of the working tree file. As the filtered version would have the CRLF line endings switched to LF line endings, checkout_is_workdir_modified returns false.
I tried to augment is_workdir_base_or_new to also compare the oid of the actual file on disk computed with git_odb__hashfile, but another test point checkout::crlf::with_ident then (sporadically!) fails. Probably a performance issue too.
Checkout logic looks quite complicated and I wonder if the cases in checkout_action_with_wd need splitting out further.
Scenario: A file is stored in the repository using LF line endings and checked out in the working tree with LF line endings. If the working tree file then has its line endings changed to CRLF, a force checkout of the file does not replace the content, and the file remains modified.
Here is a test point that fails:
I debugged this and found that checkout_is_workdir_modified compares the base/target oid with the FILTERED oid of the working tree file. As the filtered version would have the CRLF line endings switched to LF line endings, checkout_is_workdir_modified returns false.
I tried to augment is_workdir_base_or_new to also compare the oid of the actual file on disk computed with git_odb__hashfile, but another test point checkout::crlf::with_ident then (sporadically!) fails. Probably a performance issue too.
Checkout logic looks quite complicated and I wonder if the cases in checkout_action_with_wd need splitting out further.