mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-28 12:13:18 +00:00

In order to avoid racy-git, we zero out the file size for entries with the same timestamp as the index (or during the initial checkout). This is the case in a couple of crlf tests, as the code is fast enough to do everything in the same second. As we know that we do not perform the modification just after writing out the index, which is what this is designed to work around, tick the mtime of the index file such that it doesn't agree with the files anymore, and we do not zero out these entries.
392 lines
11 KiB
C
392 lines
11 KiB
C
#include "clar_libgit2.h"
|
||
#include "checkout_helpers.h"
|
||
#include "../filter/crlf.h"
|
||
|
||
#include "git2/checkout.h"
|
||
#include "repository.h"
|
||
#include "index.h"
|
||
#include "posix.h"
|
||
|
||
static git_repository *g_repo;
|
||
|
||
void test_checkout_crlf__initialize(void)
|
||
{
|
||
g_repo = cl_git_sandbox_init("crlf");
|
||
}
|
||
|
||
void test_checkout_crlf__cleanup(void)
|
||
{
|
||
cl_git_sandbox_cleanup();
|
||
}
|
||
|
||
void test_checkout_crlf__detect_crlf_autocrlf_false(void)
|
||
{
|
||
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
|
||
opts.checkout_strategy = GIT_CHECKOUT_FORCE;
|
||
|
||
cl_repo_set_bool(g_repo, "core.autocrlf", false);
|
||
|
||
git_checkout_head(g_repo, &opts);
|
||
|
||
check_file_contents("./crlf/all-lf", ALL_LF_TEXT_RAW);
|
||
check_file_contents("./crlf/all-crlf", ALL_CRLF_TEXT_RAW);
|
||
}
|
||
|
||
static void tick_index(git_index *index)
|
||
{
|
||
git_time_t ts;
|
||
struct timespec times[2];
|
||
|
||
cl_assert(index->on_disk);
|
||
cl_assert(git_index_path(index));
|
||
|
||
cl_git_pass(git_index_read(index, true));
|
||
ts = index->stamp.mtime;
|
||
|
||
times[0].tv_sec = UTIME_OMIT; /* dont' change the atime */
|
||
times[0].tv_nsec = UTIME_OMIT; /* dont' change the atime */
|
||
times[1].tv_sec = ts + 1;
|
||
times[1].tv_nsec = 0;
|
||
cl_git_pass(p_utimensat(AT_FDCWD, git_index_path(index), times, 0));
|
||
cl_git_pass(git_index_read(index, true));
|
||
}
|
||
|
||
void test_checkout_crlf__autocrlf_false_index_size_is_unfiltered_size(void)
|
||
{
|
||
git_index *index;
|
||
const git_index_entry *entry;
|
||
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
|
||
opts.checkout_strategy = GIT_CHECKOUT_FORCE;
|
||
|
||
cl_repo_set_bool(g_repo, "core.autocrlf", false);
|
||
|
||
git_repository_index(&index, g_repo);
|
||
tick_index(index);
|
||
|
||
git_checkout_head(g_repo, &opts);
|
||
|
||
cl_assert((entry = git_index_get_bypath(index, "all-lf", 0)) != NULL);
|
||
cl_assert(entry->file_size == strlen(ALL_LF_TEXT_RAW));
|
||
|
||
cl_assert((entry = git_index_get_bypath(index, "all-crlf", 0)) != NULL);
|
||
cl_assert(entry->file_size == strlen(ALL_CRLF_TEXT_RAW));
|
||
|
||
git_index_free(index);
|
||
}
|
||
|
||
void test_checkout_crlf__detect_crlf_autocrlf_true(void)
|
||
{
|
||
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
|
||
opts.checkout_strategy = GIT_CHECKOUT_FORCE;
|
||
|
||
cl_repo_set_bool(g_repo, "core.autocrlf", true);
|
||
|
||
git_checkout_head(g_repo, &opts);
|
||
|
||
if (GIT_EOL_NATIVE == GIT_EOL_LF)
|
||
check_file_contents("./crlf/all-lf", ALL_LF_TEXT_RAW);
|
||
else
|
||
check_file_contents("./crlf/all-lf", ALL_LF_TEXT_AS_CRLF);
|
||
|
||
check_file_contents("./crlf/all-crlf", ALL_CRLF_TEXT_RAW);
|
||
}
|
||
|
||
void test_checkout_crlf__more_lf_autocrlf_true(void)
|
||
{
|
||
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
|
||
opts.checkout_strategy = GIT_CHECKOUT_FORCE;
|
||
|
||
cl_repo_set_bool(g_repo, "core.autocrlf", true);
|
||
|
||
git_checkout_head(g_repo, &opts);
|
||
|
||
check_file_contents("./crlf/more-lf", MORE_LF_TEXT_RAW);
|
||
}
|
||
|
||
void test_checkout_crlf__more_crlf_autocrlf_true(void)
|
||
{
|
||
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
|
||
opts.checkout_strategy = GIT_CHECKOUT_FORCE;
|
||
|
||
cl_repo_set_bool(g_repo, "core.autocrlf", true);
|
||
|
||
git_checkout_head(g_repo, &opts);
|
||
|
||
check_file_contents("./crlf/more-crlf", MORE_CRLF_TEXT_RAW);
|
||
}
|
||
|
||
void test_checkout_crlf__all_crlf_autocrlf_true(void)
|
||
{
|
||
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
|
||
opts.checkout_strategy = GIT_CHECKOUT_FORCE;
|
||
|
||
cl_repo_set_bool(g_repo, "core.autocrlf", true);
|
||
|
||
git_checkout_head(g_repo, &opts);
|
||
|
||
check_file_contents("./crlf/all-crlf", ALL_CRLF_TEXT_RAW);
|
||
}
|
||
|
||
void test_checkout_crlf__detect_crlf_autocrlf_true_utf8(void)
|
||
{
|
||
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
|
||
opts.checkout_strategy = GIT_CHECKOUT_FORCE;
|
||
|
||
cl_repo_set_bool(g_repo, "core.autocrlf", true);
|
||
|
||
git_repository_set_head(g_repo, "refs/heads/utf8");
|
||
git_checkout_head(g_repo, &opts);
|
||
|
||
if (GIT_EOL_NATIVE == GIT_EOL_LF)
|
||
{
|
||
check_file_contents("./crlf/few-utf8-chars-lf.txt", FEW_UTF8_LF_RAW);
|
||
check_file_contents("./crlf/many-utf8-chars-lf.txt", MANY_UTF8_LF_RAW);
|
||
}
|
||
else
|
||
{
|
||
check_file_contents("./crlf/few-utf8-chars-lf.txt", FEW_UTF8_CRLF_RAW);
|
||
check_file_contents("./crlf/many-utf8-chars-lf.txt", MANY_UTF8_CRLF_RAW);
|
||
}
|
||
|
||
check_file_contents("./crlf/few-utf8-chars-crlf.txt", FEW_UTF8_CRLF_RAW);
|
||
check_file_contents("./crlf/many-utf8-chars-crlf.txt", MANY_UTF8_CRLF_RAW);
|
||
}
|
||
|
||
void test_checkout_crlf__autocrlf_true_index_size_is_filtered_size(void)
|
||
{
|
||
git_index *index;
|
||
const git_index_entry *entry;
|
||
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
|
||
opts.checkout_strategy = GIT_CHECKOUT_FORCE;
|
||
|
||
cl_repo_set_bool(g_repo, "core.autocrlf", true);
|
||
|
||
git_repository_index(&index, g_repo);
|
||
tick_index(index);
|
||
|
||
git_checkout_head(g_repo, &opts);
|
||
|
||
cl_assert((entry = git_index_get_bypath(index, "all-lf", 0)) != NULL);
|
||
|
||
if (GIT_EOL_NATIVE == GIT_EOL_LF)
|
||
cl_assert_equal_sz(strlen(ALL_LF_TEXT_RAW), entry->file_size);
|
||
else
|
||
cl_assert_equal_sz(strlen(ALL_LF_TEXT_AS_CRLF), entry->file_size);
|
||
|
||
cl_assert((entry = git_index_get_bypath(index, "all-crlf", 0)) != NULL);
|
||
cl_assert_equal_sz(strlen(ALL_CRLF_TEXT_RAW), entry->file_size);
|
||
|
||
git_index_free(index);
|
||
}
|
||
|
||
void test_checkout_crlf__with_ident(void)
|
||
{
|
||
git_index *index;
|
||
git_blob *blob;
|
||
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
|
||
opts.checkout_strategy = GIT_CHECKOUT_FORCE;
|
||
|
||
cl_git_mkfile("crlf/.gitattributes",
|
||
"*.txt text\n*.bin binary\n"
|
||
"*.crlf text eol=crlf\n"
|
||
"*.lf text eol=lf\n"
|
||
"*.ident text ident\n"
|
||
"*.identcrlf ident text eol=crlf\n"
|
||
"*.identlf ident text eol=lf\n");
|
||
|
||
cl_repo_set_bool(g_repo, "core.autocrlf", true);
|
||
|
||
/* add files with $Id$ */
|
||
|
||
cl_git_mkfile("crlf/lf.ident", ALL_LF_TEXT_RAW "\n$Id: initial content$\n");
|
||
cl_git_mkfile("crlf/crlf.ident", ALL_CRLF_TEXT_RAW "\r\n$Id$\r\n\r\n");
|
||
cl_git_mkfile("crlf/more1.identlf", "$Id$\n" MORE_LF_TEXT_RAW);
|
||
cl_git_mkfile("crlf/more2.identcrlf", "\r\n$Id: $\r\n" MORE_CRLF_TEXT_RAW);
|
||
|
||
cl_git_pass(git_repository_index(&index, g_repo));
|
||
cl_git_pass(git_index_add_bypath(index, "lf.ident"));
|
||
cl_git_pass(git_index_add_bypath(index, "crlf.ident"));
|
||
cl_git_pass(git_index_add_bypath(index, "more1.identlf"));
|
||
cl_git_pass(git_index_add_bypath(index, "more2.identcrlf"));
|
||
cl_repo_commit_from_index(NULL, g_repo, NULL, 0, "Some ident files\n");
|
||
|
||
git_checkout_head(g_repo, &opts);
|
||
|
||
/* check that blobs have $Id$ */
|
||
|
||
cl_git_pass(git_blob_lookup(&blob, g_repo,
|
||
& git_index_get_bypath(index, "lf.ident", 0)->id));
|
||
cl_assert_equal_s(
|
||
ALL_LF_TEXT_RAW "\n$Id$\n", git_blob_rawcontent(blob));
|
||
git_blob_free(blob);
|
||
|
||
cl_git_pass(git_blob_lookup(&blob, g_repo,
|
||
& git_index_get_bypath(index, "more2.identcrlf", 0)->id));
|
||
cl_assert_equal_s(
|
||
"\n$Id$\n" MORE_CRLF_TEXT_AS_LF, git_blob_rawcontent(blob));
|
||
git_blob_free(blob);
|
||
|
||
/* check that filesystem is initially untouched - matching core Git */
|
||
|
||
cl_assert_equal_file(
|
||
ALL_LF_TEXT_RAW "\n$Id: initial content$\n", 0, "crlf/lf.ident");
|
||
|
||
/* check that forced checkout rewrites correctly */
|
||
|
||
p_unlink("crlf/lf.ident");
|
||
p_unlink("crlf/crlf.ident");
|
||
p_unlink("crlf/more1.identlf");
|
||
p_unlink("crlf/more2.identcrlf");
|
||
|
||
git_checkout_head(g_repo, &opts);
|
||
|
||
if (GIT_EOL_NATIVE == GIT_EOL_LF) {
|
||
cl_assert_equal_file(
|
||
ALL_LF_TEXT_RAW
|
||
"\n$Id: fcf6d4d9c212dc66563b1171b1cd99953c756467 $\n",
|
||
0, "crlf/lf.ident");
|
||
cl_assert_equal_file(
|
||
ALL_CRLF_TEXT_AS_LF
|
||
"\n$Id: f2c66ad9b2b5a734d9bf00d5000cc10a62b8a857 $\n\n",
|
||
0, "crlf/crlf.ident");
|
||
} else {
|
||
cl_assert_equal_file(
|
||
ALL_LF_TEXT_AS_CRLF
|
||
"\r\n$Id: fcf6d4d9c212dc66563b1171b1cd99953c756467 $\r\n",
|
||
0, "crlf/lf.ident");
|
||
cl_assert_equal_file(
|
||
ALL_CRLF_TEXT_RAW
|
||
"\r\n$Id: f2c66ad9b2b5a734d9bf00d5000cc10a62b8a857 $\r\n\r\n",
|
||
0, "crlf/crlf.ident");
|
||
}
|
||
|
||
cl_assert_equal_file(
|
||
"$Id: f7830382dac1f1583422be5530fdfbd26289431b $\n"
|
||
MORE_LF_TEXT_AS_LF, 0, "crlf/more1.identlf");
|
||
|
||
cl_assert_equal_file(
|
||
"\r\n$Id: 74677a68413012ce8d7e7cfc3f12603df3a3eac4 $\r\n"
|
||
MORE_CRLF_TEXT_AS_CRLF, 0, "crlf/more2.identcrlf");
|
||
|
||
git_index_free(index);
|
||
}
|
||
|
||
void test_checkout_crlf__autocrlf_false_no_attrs(void)
|
||
{
|
||
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
|
||
opts.checkout_strategy = GIT_CHECKOUT_FORCE;
|
||
|
||
cl_repo_set_bool(g_repo, "core.autocrlf", false);
|
||
|
||
git_checkout_head(g_repo, &opts);
|
||
|
||
check_file_contents("./crlf/all-lf", ALL_LF_TEXT_RAW);
|
||
check_file_contents("./crlf/all-crlf", ALL_CRLF_TEXT_RAW);
|
||
}
|
||
|
||
void test_checkout_crlf__autocrlf_true_no_attrs(void)
|
||
{
|
||
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
|
||
opts.checkout_strategy = GIT_CHECKOUT_FORCE;
|
||
|
||
cl_repo_set_bool(g_repo, "core.autocrlf", true);
|
||
|
||
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);
|
||
}
|
||
}
|
||
|
||
void test_checkout_crlf__autocrlf_input_no_attrs(void)
|
||
{
|
||
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
|
||
opts.checkout_strategy = GIT_CHECKOUT_FORCE;
|
||
|
||
cl_repo_set_string(g_repo, "core.autocrlf", "input");
|
||
|
||
git_checkout_head(g_repo, &opts);
|
||
|
||
check_file_contents("./crlf/all-lf", ALL_LF_TEXT_RAW);
|
||
check_file_contents("./crlf/all-crlf", ALL_CRLF_TEXT_RAW);
|
||
}
|
||
|
||
void test_checkout_crlf__autocrlf_false_text_auto_attr(void)
|
||
{
|
||
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
|
||
opts.checkout_strategy = GIT_CHECKOUT_FORCE;
|
||
|
||
cl_git_mkfile("./crlf/.gitattributes", "* text=auto\n");
|
||
|
||
cl_repo_set_bool(g_repo, "core.autocrlf", false);
|
||
|
||
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);
|
||
}
|
||
}
|
||
|
||
void test_checkout_crlf__autocrlf_true_text_auto_attr(void)
|
||
{
|
||
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
|
||
opts.checkout_strategy = GIT_CHECKOUT_FORCE;
|
||
|
||
cl_git_mkfile("./crlf/.gitattributes", "* text=auto\n");
|
||
|
||
cl_repo_set_bool(g_repo, "core.autocrlf", true);
|
||
|
||
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);
|
||
}
|
||
}
|
||
|
||
void test_checkout_crlf__autocrlf_input_text_auto_attr(void)
|
||
{
|
||
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
|
||
opts.checkout_strategy = GIT_CHECKOUT_FORCE;
|
||
|
||
cl_git_mkfile("./crlf/.gitattributes", "* text=auto\n");
|
||
|
||
cl_repo_set_string(g_repo, "core.autocrlf", "input");
|
||
|
||
git_checkout_head(g_repo, &opts);
|
||
|
||
check_file_contents("./crlf/all-lf", ALL_LF_TEXT_RAW);
|
||
check_file_contents("./crlf/all-crlf", ALL_CRLF_TEXT_RAW);
|
||
}
|
||
|
||
void test_checkout_crlf__can_write_empty_file(void)
|
||
{
|
||
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
|
||
opts.checkout_strategy = GIT_CHECKOUT_FORCE;
|
||
|
||
cl_repo_set_bool(g_repo, "core.autocrlf", true);
|
||
|
||
git_repository_set_head(g_repo, "refs/heads/empty-files");
|
||
git_checkout_head(g_repo, &opts);
|
||
|
||
check_file_contents("./crlf/test1.txt", "");
|
||
|
||
if (GIT_EOL_NATIVE == GIT_EOL_LF)
|
||
check_file_contents("./crlf/test2.txt", "test2.txt's content\n");
|
||
else
|
||
check_file_contents("./crlf/test2.txt", "test2.txt's content\r\n");
|
||
|
||
check_file_contents("./crlf/test3.txt", "");
|
||
}
|