icase.c 8.13 KB
Newer Older
1 2 3
#include "clar_libgit2.h"

#include "git2/checkout.h"
4
#include "refs.h"
5
#include "path.h"
6
#include "repository.h"
7

8
#ifdef GIT_WIN32
9
# include <windows.h>
10 11
#else
# include <dirent.h>
12 13
#endif

14 15 16 17 18 19 20
static git_repository *repo;
static git_object *obj;
static git_checkout_options checkout_opts;

void test_checkout_icase__initialize(void)
{
	git_oid id;
21 22
	git_config *cfg;
	int icase = 0;
23 24 25

	repo = cl_git_sandbox_init("testrepo");

26 27 28 29 30 31 32
	cl_git_pass(git_repository_config_snapshot(&cfg, repo));
	git_config_get_bool(&icase, cfg, "core.ignorecase");
	git_config_free(cfg);

	if (!icase)
		cl_skip();

33
	cl_git_pass(git_reference_name_to_id(&id, repo, "refs/heads/dir"));
34
	cl_git_pass(git_object_lookup(&obj, repo, &id, GIT_OBJECT_ANY));
35

36
	git_checkout_options_init(&checkout_opts, GIT_CHECKOUT_OPTIONS_VERSION);
37
	checkout_opts.checkout_strategy = GIT_CHECKOUT_NONE;
38 39 40 41 42 43 44 45
}

void test_checkout_icase__cleanup(void)
{
	git_object_free(obj);
	cl_git_sandbox_cleanup();
}

46
static char *get_filename(const char *in)
47
{
48
	char *search_dirname, *search_filename, *filename = NULL;
49
	git_str out = GIT_STR_INIT;
50 51 52
	DIR *dir;
	struct dirent *de;

53 54
	cl_assert(search_dirname = git_fs_path_dirname(in));
	cl_assert(search_filename = git_fs_path_basename(in));
55 56 57 58 59

	cl_assert(dir = opendir(search_dirname));

	while ((de = readdir(dir))) {
		if (strcasecmp(de->d_name, search_filename) == 0) {
60 61
			git_str_join(&out, '/', search_dirname, de->d_name);
			filename = git_str_detach(&out);
62 63 64 65 66 67 68 69
			break;
		}
	}

	closedir(dir);

	git__free(search_dirname);
	git__free(search_filename);
70
	git_str_dispose(&out);
71 72

	return filename;
73 74
}

75 76 77 78 79
static void assert_name_is(const char *expected)
{
	char *actual;
	size_t actual_len, expected_len, start;

80
	cl_assert(actual = get_filename(expected));
81 82 83 84 85 86 87 88 89 90 91 92 93 94

	expected_len = strlen(expected);
	actual_len = strlen(actual);
	cl_assert(actual_len >= expected_len);

	start = actual_len - expected_len;
	cl_assert_equal_s(expected, actual + start);

	if (start)
		cl_assert_equal_strn("/", actual + (start - 1), 1);

	free(actual);
}

95 96 97 98
static int symlink_or_fake(git_repository *repo, const char *a, const char *b)
{
	int symlinks;

99
	cl_git_pass(git_repository__configmap_lookup(&symlinks, repo, GIT_CONFIGMAP_SYMLINKS));
100 101 102 103 104 105 106

	if (symlinks)
		return p_symlink(a, b);
	else
		return git_futils_fake_symlink(a, b);
}

107 108 109 110 111 112 113 114 115 116 117 118
void test_checkout_icase__refuses_to_overwrite_files_for_files(void)
{
	checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE|GIT_CHECKOUT_RECREATE_MISSING;

	cl_git_write2file("testrepo/BRANCH_FILE.txt", "neue file\n", 10, \
		O_WRONLY | O_CREAT | O_TRUNC, 0644);

	cl_git_fail(git_checkout_tree(repo, obj, &checkout_opts));
	assert_name_is("testrepo/BRANCH_FILE.txt");
}

void test_checkout_icase__overwrites_files_for_files_when_forced(void)
119
{
120 121
	checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE;

122 123 124 125 126 127 128
	cl_git_write2file("testrepo/NEW.txt", "neue file\n", 10, \
		O_WRONLY | O_CREAT | O_TRUNC, 0644);

	cl_git_pass(git_checkout_tree(repo, obj, &checkout_opts));
	assert_name_is("testrepo/new.txt");
}

129
void test_checkout_icase__refuses_to_overwrite_links_for_files(void)
130
{
131 132
	checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE|GIT_CHECKOUT_RECREATE_MISSING;

133
	cl_must_pass(symlink_or_fake(repo, "../tmp", "testrepo/BRANCH_FILE.txt"));
134 135 136

	cl_git_fail(git_checkout_tree(repo, obj, &checkout_opts));

137
	cl_assert(!git_fs_path_exists("tmp"));
138 139 140 141 142 143 144
	assert_name_is("testrepo/BRANCH_FILE.txt");
}

void test_checkout_icase__overwrites_links_for_files_when_forced(void)
{
	checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE;

145
	cl_must_pass(symlink_or_fake(repo, "../tmp", "testrepo/NEW.txt"));
146 147 148

	cl_git_pass(git_checkout_tree(repo, obj, &checkout_opts));

149
	cl_assert(!git_fs_path_exists("tmp"));
150 151 152
	assert_name_is("testrepo/new.txt");
}

153 154 155 156 157 158 159 160 161
void test_checkout_icase__overwrites_empty_folders_for_files(void)
{
	checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE|GIT_CHECKOUT_RECREATE_MISSING;

	cl_must_pass(p_mkdir("testrepo/NEW.txt", 0777));

	cl_git_pass(git_checkout_tree(repo, obj, &checkout_opts));

	assert_name_is("testrepo/new.txt");
162
	cl_assert(!git_fs_path_isdir("testrepo/new.txt"));
163 164 165 166 167 168 169 170 171 172 173 174 175
}

void test_checkout_icase__refuses_to_overwrite_populated_folders_for_files(void)
{
	checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE|GIT_CHECKOUT_RECREATE_MISSING;

	cl_must_pass(p_mkdir("testrepo/BRANCH_FILE.txt", 0777));
	cl_git_write2file("testrepo/BRANCH_FILE.txt/foobar", "neue file\n", 10, \
		O_WRONLY | O_CREAT | O_TRUNC, 0644);

	cl_git_fail(git_checkout_tree(repo, obj, &checkout_opts));

	assert_name_is("testrepo/BRANCH_FILE.txt");
176
	cl_assert(git_fs_path_isdir("testrepo/BRANCH_FILE.txt"));
177 178 179
}

void test_checkout_icase__overwrites_folders_for_files_when_forced(void)
180
{
181 182
	checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE;

183
	cl_must_pass(p_mkdir("testrepo/NEW.txt", 0777));
184 185
	cl_git_write2file("testrepo/NEW.txt/foobar", "neue file\n", 10, \
		O_WRONLY | O_CREAT | O_TRUNC, 0644);
186 187 188 189

	cl_git_pass(git_checkout_tree(repo, obj, &checkout_opts));

	assert_name_is("testrepo/new.txt");
190
	cl_assert(!git_fs_path_isdir("testrepo/new.txt"));
191 192
}

193
void test_checkout_icase__refuses_to_overwrite_files_for_folders(void)
194
{
195 196 197 198 199 200 201
	checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE|GIT_CHECKOUT_RECREATE_MISSING;

	cl_git_write2file("testrepo/A", "neue file\n", 10, \
		O_WRONLY | O_CREAT | O_TRUNC, 0644);

	cl_git_fail(git_checkout_tree(repo, obj, &checkout_opts));
	assert_name_is("testrepo/A");
202
	cl_assert(!git_fs_path_isdir("testrepo/A"));
203 204 205 206 207 208
}

void test_checkout_icase__overwrites_files_for_folders_when_forced(void)
{
	checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE;

209 210 211 212 213
	cl_git_write2file("testrepo/A", "neue file\n", 10, \
		O_WRONLY | O_CREAT | O_TRUNC, 0644);

	cl_git_pass(git_checkout_tree(repo, obj, &checkout_opts));
	assert_name_is("testrepo/a");
214
	cl_assert(git_fs_path_isdir("testrepo/a"));
215 216
}

217 218 219 220
void test_checkout_icase__refuses_to_overwrite_links_for_folders(void)
{
	checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE|GIT_CHECKOUT_RECREATE_MISSING;

221
	cl_must_pass(symlink_or_fake(repo, "..", "testrepo/A"));
222 223 224

	cl_git_fail(git_checkout_tree(repo, obj, &checkout_opts));

225
	cl_assert(!git_fs_path_exists("b.txt"));
226 227 228 229
	assert_name_is("testrepo/A");
}

void test_checkout_icase__overwrites_links_for_folders_when_forced(void)
230
{
231 232
	checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE;

233
	cl_must_pass(symlink_or_fake(repo, "..", "testrepo/A"));
234 235 236

	cl_git_pass(git_checkout_tree(repo, obj, &checkout_opts));

237
	cl_assert(!git_fs_path_exists("b.txt"));
238 239
	assert_name_is("testrepo/a");
}
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260

void test_checkout_icase__ignores_unstaged_casechange(void)
{
	git_reference *orig_ref, *br2_ref;
	git_commit *orig, *br2;
	git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;

	checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE;

	cl_git_pass(git_reference_lookup_resolved(&orig_ref, repo, "HEAD", 100));
	cl_git_pass(git_commit_lookup(&orig, repo, git_reference_target(orig_ref)));
	cl_git_pass(git_reset(repo, (git_object *)orig, GIT_RESET_HARD, NULL));

	cl_rename("testrepo/branch_file.txt", "testrepo/Branch_File.txt");

	cl_git_pass(git_reference_lookup_resolved(&br2_ref, repo, "refs/heads/br2", 100));
	cl_git_pass(git_commit_lookup(&br2, repo, git_reference_target(br2_ref)));

	cl_git_pass(git_checkout_tree(repo, (const git_object *)br2, &checkout_opts));

	git_commit_free(orig);
261
	git_commit_free(br2);
262
	git_reference_free(orig_ref);
263
	git_reference_free(br2_ref);
264 265 266 267 268 269 270 271 272 273 274 275
}

void test_checkout_icase__conflicts_with_casechanged_subtrees(void)
{
	git_reference *orig_ref;
	git_object *orig, *subtrees;
	git_oid oid;
	git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;

	checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE;

	cl_git_pass(git_reference_lookup_resolved(&orig_ref, repo, "HEAD", 100));
276
	cl_git_pass(git_object_lookup(&orig, repo, git_reference_target(orig_ref), GIT_OBJECT_COMMIT));
277 278 279 280 281 282 283
	cl_git_pass(git_reset(repo, (git_object *)orig, GIT_RESET_HARD, NULL));

	cl_must_pass(p_mkdir("testrepo/AB", 0777));
	cl_must_pass(p_mkdir("testrepo/AB/C", 0777));
	cl_git_write2file("testrepo/AB/C/3.txt", "Foobar!\n", 8, O_RDWR|O_CREAT, 0666);

	cl_git_pass(git_reference_name_to_id(&oid, repo, "refs/heads/subtrees"));
284
	cl_git_pass(git_object_lookup(&subtrees, repo, &oid, GIT_OBJECT_ANY));
285 286 287 288 289 290 291 292

	cl_git_fail(git_checkout_tree(repo, subtrees, &checkout_opts));

	git_object_free(orig);
	git_object_free(subtrees);
    git_reference_free(orig_ref);
}