core.c 21.1 KB
Newer Older
1
#include "clar_libgit2.h"
2
#include "fs_path.h"
3
#include "path.h"
4

5 6 7 8 9
void test_path_core__cleanup(void)
{
	cl_git_sandbox_cleanup();
}

10 11 12 13 14 15
static void test_make_relative(
	const char *expected_path,
	const char *path,
	const char *parent,
	int expected_status)
{
16 17
	git_str buf = GIT_STR_INIT;
	git_str_puts(&buf, path);
18
	cl_assert_equal_i(expected_status, git_fs_path_make_relative(&buf, parent));
19
	cl_assert_equal_s(expected_path, buf.ptr);
20
	git_str_dispose(&buf);
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
}

void test_path_core__make_relative(void)
{
	test_make_relative("foo.c", "/path/to/foo.c", "/path/to", 0);
	test_make_relative("bar/foo.c", "/path/to/bar/foo.c", "/path/to", 0);
	test_make_relative("foo.c", "/path/to/foo.c", "/path/to/", 0);

	test_make_relative("", "/path/to", "/path/to", 0);
	test_make_relative("", "/path/to", "/path/to/", 0);

	test_make_relative("../", "/path/to", "/path/to/foo", 0);

	test_make_relative("../foo.c", "/path/to/foo.c", "/path/to/bar", 0);
	test_make_relative("../bar/foo.c", "/path/to/bar/foo.c", "/path/to/baz", 0);

	test_make_relative("../../foo.c", "/path/to/foo.c", "/path/to/foo/bar", 0);
	test_make_relative("../../foo/bar.c", "/path/to/foo/bar.c", "/path/to/bar/foo", 0);

	test_make_relative("../../foo.c", "/foo.c", "/bar/foo", 0);

	test_make_relative("foo.c", "/path/to/foo.c", "/path/to/", 0);
	test_make_relative("../foo.c", "/path/to/foo.c", "/path/to/bar/", 0);

	test_make_relative("foo.c", "d:/path/to/foo.c", "d:/path/to", 0);

	test_make_relative("../foo", "/foo", "/bar", 0);
	test_make_relative("path/to/foo.c", "/path/to/foo.c", "/", 0);
	test_make_relative("../foo", "path/to/foo", "path/to/bar", 0);

	test_make_relative("/path/to/foo.c", "/path/to/foo.c", "d:/path/to", GIT_ENOTFOUND);
	test_make_relative("d:/path/to/foo.c", "d:/path/to/foo.c", "/path/to", GIT_ENOTFOUND);
53

54 55
	test_make_relative("/path/to/foo.c", "/path/to/foo.c", "not-a-rooted-path", GIT_ENOTFOUND);
	test_make_relative("not-a-rooted-path", "not-a-rooted-path", "/path/to", GIT_ENOTFOUND);
56

57 58 59
	test_make_relative("/path", "/path", "pathtofoo", GIT_ENOTFOUND);
	test_make_relative("path", "path", "pathtofoo", GIT_ENOTFOUND);
}
60 61 62

void test_path_core__isvalid_standard(void)
{
63 64 65
	cl_assert_equal_b(true, git_fs_path_is_valid("foo/bar", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("foo/bar/file.txt", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("foo/bar/.file", 0));
66 67
}

68 69 70 71
/* Ensure that `is_valid_str` only reads str->size bytes */
void test_path_core__isvalid_standard_str(void)
{
	git_str str = GIT_STR_INIT_CONST("foo/bar//zap", 0);
72
	unsigned int flags = GIT_FS_PATH_REJECT_EMPTY_COMPONENT;
73 74

	str.size = 0;
75
	cl_assert_equal_b(false, git_fs_path_str_is_valid(&str, flags));
76 77

	str.size = 3;
78
	cl_assert_equal_b(true, git_fs_path_str_is_valid(&str, flags));
79 80

	str.size = 4;
81
	cl_assert_equal_b(false, git_fs_path_str_is_valid(&str, flags));
82 83

	str.size = 5;
84
	cl_assert_equal_b(true, git_fs_path_str_is_valid(&str, flags));
85 86

	str.size = 7;
87
	cl_assert_equal_b(true, git_fs_path_str_is_valid(&str, flags));
88 89

	str.size = 8;
90
	cl_assert_equal_b(false, git_fs_path_str_is_valid(&str, flags));
91 92

	str.size = strlen(str.ptr);
93
	cl_assert_equal_b(false, git_fs_path_str_is_valid(&str, flags));
94 95
}

96 97
void test_path_core__isvalid_empty_dir_component(void)
{
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
	unsigned int flags = GIT_FS_PATH_REJECT_EMPTY_COMPONENT;

	/* empty component */
	cl_assert_equal_b(true, git_fs_path_is_valid("foo//bar", 0));

	/* leading slash */
	cl_assert_equal_b(true, git_fs_path_is_valid("/", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("/foo", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("/foo/bar", 0));

	/* trailing slash */
	cl_assert_equal_b(true, git_fs_path_is_valid("foo/", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("foo/bar/", 0));


	/* empty component */
	cl_assert_equal_b(false, git_fs_path_is_valid("foo//bar", flags));
115 116

	/* leading slash */
117 118 119
	cl_assert_equal_b(false, git_fs_path_is_valid("/", flags));
	cl_assert_equal_b(false, git_fs_path_is_valid("/foo", flags));
	cl_assert_equal_b(false, git_fs_path_is_valid("/foo/bar", flags));
120 121

	/* trailing slash */
122 123
	cl_assert_equal_b(false, git_fs_path_is_valid("foo/", flags));
	cl_assert_equal_b(false, git_fs_path_is_valid("foo/bar/", flags));
124 125 126 127
}

void test_path_core__isvalid_dot_and_dotdot(void)
{
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
	cl_assert_equal_b(true, git_fs_path_is_valid(".", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("./foo", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("foo/.", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("./foo", 0));

	cl_assert_equal_b(true, git_fs_path_is_valid("..", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("../foo", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("foo/..", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("../foo", 0));

	cl_assert_equal_b(false, git_fs_path_is_valid(".", GIT_FS_PATH_REJECT_TRAVERSAL));
	cl_assert_equal_b(false, git_fs_path_is_valid("./foo", GIT_FS_PATH_REJECT_TRAVERSAL));
	cl_assert_equal_b(false, git_fs_path_is_valid("foo/.", GIT_FS_PATH_REJECT_TRAVERSAL));
	cl_assert_equal_b(false, git_fs_path_is_valid("./foo", GIT_FS_PATH_REJECT_TRAVERSAL));

	cl_assert_equal_b(false, git_fs_path_is_valid("..", GIT_FS_PATH_REJECT_TRAVERSAL));
	cl_assert_equal_b(false, git_fs_path_is_valid("../foo", GIT_FS_PATH_REJECT_TRAVERSAL));
	cl_assert_equal_b(false, git_fs_path_is_valid("foo/..", GIT_FS_PATH_REJECT_TRAVERSAL));
	cl_assert_equal_b(false, git_fs_path_is_valid("../foo", GIT_FS_PATH_REJECT_TRAVERSAL));
147 148 149 150
}

void test_path_core__isvalid_backslash(void)
{
151 152 153
	cl_assert_equal_b(true, git_fs_path_is_valid("foo\\file.txt", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("foo/bar\\file.txt", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("foo/bar\\", 0));
154

155 156 157
	cl_assert_equal_b(false, git_fs_path_is_valid("foo\\file.txt", GIT_FS_PATH_REJECT_BACKSLASH));
	cl_assert_equal_b(false, git_fs_path_is_valid("foo/bar\\file.txt", GIT_FS_PATH_REJECT_BACKSLASH));
	cl_assert_equal_b(false, git_fs_path_is_valid("foo/bar\\", GIT_FS_PATH_REJECT_BACKSLASH));
158 159 160 161
}

void test_path_core__isvalid_trailing_dot(void)
{
162 163 164 165 166 167 168 169 170
	cl_assert_equal_b(true, git_fs_path_is_valid("foo.", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("foo...", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("foo/bar.", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("foo./bar", 0));

	cl_assert_equal_b(false, git_fs_path_is_valid("foo.", GIT_FS_PATH_REJECT_TRAILING_DOT));
	cl_assert_equal_b(false, git_fs_path_is_valid("foo...", GIT_FS_PATH_REJECT_TRAILING_DOT));
	cl_assert_equal_b(false, git_fs_path_is_valid("foo/bar.", GIT_FS_PATH_REJECT_TRAILING_DOT));
	cl_assert_equal_b(false, git_fs_path_is_valid("foo./bar", GIT_FS_PATH_REJECT_TRAILING_DOT));
171 172 173 174
}

void test_path_core__isvalid_trailing_space(void)
{
175 176 177 178 179 180 181 182 183 184 185
	cl_assert_equal_b(true, git_fs_path_is_valid("foo ", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("foo   ", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("foo/bar ", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid(" ", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("foo /bar", 0));

	cl_assert_equal_b(false, git_fs_path_is_valid("foo ", GIT_FS_PATH_REJECT_TRAILING_SPACE));
	cl_assert_equal_b(false, git_fs_path_is_valid("foo   ", GIT_FS_PATH_REJECT_TRAILING_SPACE));
	cl_assert_equal_b(false, git_fs_path_is_valid("foo/bar ", GIT_FS_PATH_REJECT_TRAILING_SPACE));
	cl_assert_equal_b(false, git_fs_path_is_valid(" ", GIT_FS_PATH_REJECT_TRAILING_SPACE));
	cl_assert_equal_b(false, git_fs_path_is_valid("foo /bar", GIT_FS_PATH_REJECT_TRAILING_SPACE));
186 187 188 189
}

void test_path_core__isvalid_trailing_colon(void)
{
190 191 192 193 194 195 196 197 198
	cl_assert_equal_b(true, git_fs_path_is_valid("foo:", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("foo/bar:", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid(":", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("foo:/bar", 0));

	cl_assert_equal_b(false, git_fs_path_is_valid("foo:", GIT_FS_PATH_REJECT_TRAILING_COLON));
	cl_assert_equal_b(false, git_fs_path_is_valid("foo/bar:", GIT_FS_PATH_REJECT_TRAILING_COLON));
	cl_assert_equal_b(false, git_fs_path_is_valid(":", GIT_FS_PATH_REJECT_TRAILING_COLON));
	cl_assert_equal_b(false, git_fs_path_is_valid("foo:/bar", GIT_FS_PATH_REJECT_TRAILING_COLON));
199 200 201 202
}

void test_path_core__isvalid_dos_paths(void)
{
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
	cl_assert_equal_b(true, git_fs_path_is_valid("aux", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("aux.", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("aux:", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("aux.asdf", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("aux.asdf\\zippy", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("aux:asdf\\foobar", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("con", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("prn", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("nul", 0));

	cl_assert_equal_b(false, git_fs_path_is_valid("aux", GIT_FS_PATH_REJECT_DOS_PATHS));
	cl_assert_equal_b(false, git_fs_path_is_valid("aux.", GIT_FS_PATH_REJECT_DOS_PATHS));
	cl_assert_equal_b(false, git_fs_path_is_valid("aux:", GIT_FS_PATH_REJECT_DOS_PATHS));
	cl_assert_equal_b(false, git_fs_path_is_valid("aux.asdf", GIT_FS_PATH_REJECT_DOS_PATHS));
	cl_assert_equal_b(false, git_fs_path_is_valid("aux.asdf\\zippy", GIT_FS_PATH_REJECT_DOS_PATHS));
	cl_assert_equal_b(false, git_fs_path_is_valid("aux:asdf\\foobar", GIT_FS_PATH_REJECT_DOS_PATHS));
	cl_assert_equal_b(false, git_fs_path_is_valid("con", GIT_FS_PATH_REJECT_DOS_PATHS));
	cl_assert_equal_b(false, git_fs_path_is_valid("prn", GIT_FS_PATH_REJECT_DOS_PATHS));
	cl_assert_equal_b(false, git_fs_path_is_valid("nul", GIT_FS_PATH_REJECT_DOS_PATHS));

	cl_assert_equal_b(true, git_fs_path_is_valid("aux1", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("aux1", GIT_FS_PATH_REJECT_DOS_PATHS));
	cl_assert_equal_b(true, git_fs_path_is_valid("auxn", GIT_FS_PATH_REJECT_DOS_PATHS));
	cl_assert_equal_b(true, git_fs_path_is_valid("aux\\foo", GIT_FS_PATH_REJECT_DOS_PATHS));
227 228 229 230
}

void test_path_core__isvalid_dos_paths_withnum(void)
{
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
	cl_assert_equal_b(true, git_fs_path_is_valid("com1", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("com1.", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("com1:", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("com1.asdf", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("com1.asdf\\zippy", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("com1:asdf\\foobar", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("com1\\foo", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("lpt1", 0));

	cl_assert_equal_b(false, git_fs_path_is_valid("com1", GIT_FS_PATH_REJECT_DOS_PATHS));
	cl_assert_equal_b(false, git_fs_path_is_valid("com1.", GIT_FS_PATH_REJECT_DOS_PATHS));
	cl_assert_equal_b(false, git_fs_path_is_valid("com1:", GIT_FS_PATH_REJECT_DOS_PATHS));
	cl_assert_equal_b(false, git_fs_path_is_valid("com1.asdf", GIT_FS_PATH_REJECT_DOS_PATHS));
	cl_assert_equal_b(false, git_fs_path_is_valid("com1.asdf\\zippy", GIT_FS_PATH_REJECT_DOS_PATHS));
	cl_assert_equal_b(false, git_fs_path_is_valid("com1:asdf\\foobar", GIT_FS_PATH_REJECT_DOS_PATHS));
	cl_assert_equal_b(false, git_fs_path_is_valid("com1/foo", GIT_FS_PATH_REJECT_DOS_PATHS));
	cl_assert_equal_b(false, git_fs_path_is_valid("lpt1", GIT_FS_PATH_REJECT_DOS_PATHS));

	cl_assert_equal_b(true, git_fs_path_is_valid("com0", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("com0", GIT_FS_PATH_REJECT_DOS_PATHS));
	cl_assert_equal_b(true, git_fs_path_is_valid("com10", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("com10", GIT_FS_PATH_REJECT_DOS_PATHS));
	cl_assert_equal_b(true, git_fs_path_is_valid("comn", GIT_FS_PATH_REJECT_DOS_PATHS));
	cl_assert_equal_b(true, git_fs_path_is_valid("com1\\foo", GIT_FS_PATH_REJECT_DOS_PATHS));
	cl_assert_equal_b(true, git_fs_path_is_valid("lpt0", GIT_FS_PATH_REJECT_DOS_PATHS));
	cl_assert_equal_b(true, git_fs_path_is_valid("lpt10", GIT_FS_PATH_REJECT_DOS_PATHS));
	cl_assert_equal_b(true, git_fs_path_is_valid("lptn", GIT_FS_PATH_REJECT_DOS_PATHS));
258 259
}

260
void test_path_core__isvalid_nt_chars(void)
261
{
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280
	cl_assert_equal_b(true, git_fs_path_is_valid("asdf\001foo", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("asdf\037bar", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("asdf<bar", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("asdf>foo", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("asdf:foo", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("asdf\"bar", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("asdf|foo", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("asdf?bar", 0));
	cl_assert_equal_b(true, git_fs_path_is_valid("asdf*bar", 0));

	cl_assert_equal_b(false, git_fs_path_is_valid("asdf\001foo", GIT_FS_PATH_REJECT_NT_CHARS));
	cl_assert_equal_b(false, git_fs_path_is_valid("asdf\037bar", GIT_FS_PATH_REJECT_NT_CHARS));
	cl_assert_equal_b(false, git_fs_path_is_valid("asdf<bar", GIT_FS_PATH_REJECT_NT_CHARS));
	cl_assert_equal_b(false, git_fs_path_is_valid("asdf>foo", GIT_FS_PATH_REJECT_NT_CHARS));
	cl_assert_equal_b(false, git_fs_path_is_valid("asdf:foo", GIT_FS_PATH_REJECT_NT_CHARS));
	cl_assert_equal_b(false, git_fs_path_is_valid("asdf\"bar", GIT_FS_PATH_REJECT_NT_CHARS));
	cl_assert_equal_b(false, git_fs_path_is_valid("asdf|foo", GIT_FS_PATH_REJECT_NT_CHARS));
	cl_assert_equal_b(false, git_fs_path_is_valid("asdf?bar", GIT_FS_PATH_REJECT_NT_CHARS));
	cl_assert_equal_b(false, git_fs_path_is_valid("asdf*bar", GIT_FS_PATH_REJECT_NT_CHARS));
281
}
282

283 284
void test_path_core__validate_workdir(void)
{
285 286 287 288 289
	cl_must_pass(git_path_validate_length(NULL, "/foo/bar"));
	cl_must_pass(git_path_validate_length(NULL, "C:\\Foo\\Bar"));
	cl_must_pass(git_path_validate_length(NULL, "\\\\?\\C:\\Foo\\Bar"));
	cl_must_pass(git_path_validate_length(NULL, "\\\\?\\C:\\Foo\\Bar"));
	cl_must_pass(git_path_validate_length(NULL, "\\\\?\\UNC\\server\\C$\\folder"));
290 291 292 293 294 295

#ifdef GIT_WIN32
	/*
	 * In the absense of a repo configuration, 259 character paths
	 * succeed. >= 260 character paths fail.
	 */
296 297 298
	cl_must_pass(git_path_validate_length(NULL, "C:\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\ok.txt"));
	cl_must_pass(git_path_validate_length(NULL, "C:\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\260.txt"));
	cl_must_fail(git_path_validate_length(NULL, "C:\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\longer_than_260.txt"));
299 300

	/* count characters, not bytes */
301 302
	cl_must_pass(git_path_validate_length(NULL, "C:\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\\260.txt"));
	cl_must_fail(git_path_validate_length(NULL, "C:\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\\long.txt"));
303
#else
304 305 306 307 308
	cl_must_pass(git_path_validate_length(NULL, "/c/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/ok.txt"));
	cl_must_pass(git_path_validate_length(NULL, "/c/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/260.txt"));
	cl_must_pass(git_path_validate_length(NULL, "/c/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/longer_than_260.txt"));
	cl_must_pass(git_path_validate_length(NULL, "C:\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\\260.txt"));
	cl_must_pass(git_path_validate_length(NULL, "C:\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\\long.txt"));
309 310 311 312 313 314 315 316 317 318 319 320 321 322 323
#endif
}

void test_path_core__validate_workdir_with_core_longpath(void)
{
#ifdef GIT_WIN32
	git_repository *repo;
	git_config *config;

	repo = cl_git_sandbox_init("empty_bare.git");

	cl_git_pass(git_repository_open(&repo, "empty_bare.git"));
	cl_git_pass(git_repository_config(&config, repo));

	/* fail by default */
324
	cl_must_fail(git_path_validate_length(repo, "/c/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/longer_than_260.txt"));
325 326 327

	/* set core.longpaths explicitly on */
	cl_git_pass(git_config_set_bool(config, "core.longpaths", 1));
328
	cl_must_pass(git_path_validate_length(repo, "/c/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/longer_than_260.txt"));
329 330 331

	/* set core.longpaths explicitly off */
	cl_git_pass(git_config_set_bool(config, "core.longpaths", 0));
332
	cl_must_fail(git_path_validate_length(repo, "/c/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/longer_than_260.txt"));
333 334 335

	git_config_free(config);
	git_repository_free(repo);
336 337 338
#endif
}

339 340 341 342 343 344
static void test_join_unrooted(
	const char *expected_result,
	ssize_t expected_rootlen,
	const char *path,
	const char *base)
{
345
	git_str result = GIT_STR_INIT;
346 347
	ssize_t root_at;

348
	cl_git_pass(git_fs_path_join_unrooted(&result, path, base, &root_at));
349 350 351
	cl_assert_equal_s(expected_result, result.ptr);
	cl_assert_equal_i(expected_rootlen, root_at);

352
	git_str_dispose(&result);
353 354 355 356
}

void test_path_core__join_unrooted(void)
{
357
	git_str out = GIT_STR_INIT;
358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375

	test_join_unrooted("foo", 0, "foo", NULL);
	test_join_unrooted("foo/bar", 0, "foo/bar", NULL);

	/* Relative paths have base prepended */
	test_join_unrooted("/foo/bar", 4, "bar", "/foo");
	test_join_unrooted("/foo/bar/foobar", 4, "bar/foobar", "/foo");
	test_join_unrooted("c:/foo/bar/foobar", 6, "bar/foobar", "c:/foo");
	test_join_unrooted("c:/foo/bar/foobar", 10, "foobar", "c:/foo/bar");

	/* Absolute paths are not prepended with base */
	test_join_unrooted("/foo", 0, "/foo", "/asdf");
	test_join_unrooted("/foo/bar", 0, "/foo/bar", "/asdf");

	/* Drive letter is given as root length on Windows */
	test_join_unrooted("c:/foo", 2, "c:/foo", "c:/asdf");
	test_join_unrooted("c:/foo/bar", 2, "c:/foo/bar", "c:/asdf");

376 377 378 379 380 381 382 383 384 385
#ifdef GIT_WIN32
	/* Paths starting with '\\' are absolute */
	test_join_unrooted("\\bar", 0, "\\bar", "c:/foo/");
	test_join_unrooted("\\\\network\\bar", 9, "\\\\network\\bar", "c:/foo/");
#else
	/* Paths starting with '\\' are not absolute on non-Windows systems */
	test_join_unrooted("/foo/\\bar", 4, "\\bar", "/foo");
	test_join_unrooted("c:/foo/\\bar", 7, "\\bar", "c:/foo/");
#endif

386 387 388 389 390 391 392
	/* Base is returned when it's provided and is the prefix */
	test_join_unrooted("c:/foo/bar/foobar", 6, "c:/foo/bar/foobar", "c:/foo");
	test_join_unrooted("c:/foo/bar/foobar", 10, "c:/foo/bar/foobar", "c:/foo/bar");

	/* Trailing slash in the base is ignored */
	test_join_unrooted("c:/foo/bar/foobar", 6, "c:/foo/bar/foobar", "c:/foo/");

393
	git_str_dispose(&out);
394
}
395 396 397 398 399 400 401 402 403 404 405

void test_path_core__join_unrooted_respects_funny_windows_roots(void)
{
	test_join_unrooted("💩:/foo/bar/foobar", 9, "bar/foobar", "💩:/foo");
	test_join_unrooted("💩:/foo/bar/foobar", 13, "foobar", "💩:/foo/bar");
	test_join_unrooted("💩:/foo", 5, "💩:/foo", "💩:/asdf");
	test_join_unrooted("💩:/foo/bar", 5, "💩:/foo/bar", "💩:/asdf");
	test_join_unrooted("💩:/foo/bar/foobar", 9, "💩:/foo/bar/foobar", "💩:/foo");
	test_join_unrooted("💩:/foo/bar/foobar", 13, "💩:/foo/bar/foobar", "💩:/foo/bar");
	test_join_unrooted("💩:/foo/bar/foobar", 9, "💩:/foo/bar/foobar", "💩:/foo/");
}