normalize.c 14.2 KB
Newer Older
Ben Straub committed
1 2 3 4 5 6
#include "clar_libgit2.h"

#include "repository.h"
#include "git2/reflog.h"
#include "reflog.h"

7
/* Helpers */
8 9 10 11
static void ensure_refname_normalized(
	unsigned int flags,
	const char *input_refname,
	const char *expected_refname)
Ben Straub committed
12 13 14
{
	char buffer_out[GIT_REFNAME_MAX];

15
	cl_git_pass(git_reference_normalize_name(buffer_out, sizeof(buffer_out), input_refname, flags));
Ben Straub committed
16

17
	cl_assert_equal_s(expected_refname, buffer_out);
18
}
Ben Straub committed
19

20
static void ensure_refname_invalid(unsigned int flags, const char *input_refname)
21 22
{
	char buffer_out[GIT_REFNAME_MAX];
Ben Straub committed
23

24 25 26
	cl_assert_equal_i(
		GIT_EINVALIDSPEC,
		git_reference_normalize_name(buffer_out, sizeof(buffer_out), input_refname, flags));
Ben Straub committed
27 28
}

29 30 31
void test_refs_normalize__can_normalize_a_direct_reference_name(void)
{
	ensure_refname_normalized(
32
		GIT_REFERENCE_FORMAT_NORMAL, "refs/dummy/a", "refs/dummy/a");
33
	ensure_refname_normalized(
34
		GIT_REFERENCE_FORMAT_NORMAL, "refs/stash", "refs/stash");
35
	ensure_refname_normalized(
36
		GIT_REFERENCE_FORMAT_NORMAL, "refs/tags/a", "refs/tags/a");
37
	ensure_refname_normalized(
38
		GIT_REFERENCE_FORMAT_NORMAL, "refs/heads/a/b", "refs/heads/a/b");
39
	ensure_refname_normalized(
40
		GIT_REFERENCE_FORMAT_NORMAL, "refs/heads/a./b", "refs/heads/a./b");
41
	ensure_refname_normalized(
42
		GIT_REFERENCE_FORMAT_NORMAL, "refs/heads/v@ation", "refs/heads/v@ation");
43
	ensure_refname_normalized(
44
		GIT_REFERENCE_FORMAT_NORMAL, "refs///heads///a", "refs/heads/a");
45
}
Ben Straub committed
46

47
void test_refs_normalize__cannot_normalize_any_direct_reference_name(void)
Ben Straub committed
48
{
49
	ensure_refname_invalid(
50
		GIT_REFERENCE_FORMAT_NORMAL, "a");
51
	ensure_refname_invalid(
52
		GIT_REFERENCE_FORMAT_NORMAL, "/a");
53
	ensure_refname_invalid(
54
		GIT_REFERENCE_FORMAT_NORMAL, "//a");
55
	ensure_refname_invalid(
56
		GIT_REFERENCE_FORMAT_NORMAL, "");
57
	ensure_refname_invalid(
58
		GIT_REFERENCE_FORMAT_NORMAL, "/refs/heads/a/");
59
	ensure_refname_invalid(
60
		GIT_REFERENCE_FORMAT_NORMAL, "refs/heads/a/");
61
	ensure_refname_invalid(
62
		GIT_REFERENCE_FORMAT_NORMAL, "refs/heads/a.");
63
	ensure_refname_invalid(
64
		GIT_REFERENCE_FORMAT_NORMAL, "refs/heads/a.lock");
65
	ensure_refname_invalid(
66
		GIT_REFERENCE_FORMAT_NORMAL, "refs/heads/foo?bar");
67
	ensure_refname_invalid(
68
		GIT_REFERENCE_FORMAT_NORMAL, "refs/heads\foo");
69
	ensure_refname_normalized(
70
		GIT_REFERENCE_FORMAT_NORMAL, "refs/heads/v@ation", "refs/heads/v@ation");
71
	ensure_refname_normalized(
72
		GIT_REFERENCE_FORMAT_NORMAL, "refs///heads///a", "refs/heads/a");
73
	ensure_refname_invalid(
74
		GIT_REFERENCE_FORMAT_NORMAL, "refs/heads/.a/b");
75
	ensure_refname_invalid(
76
		GIT_REFERENCE_FORMAT_NORMAL, "refs/heads/foo/../bar");
77
	ensure_refname_invalid(
78
		GIT_REFERENCE_FORMAT_NORMAL, "refs/heads/foo..bar");
79
	ensure_refname_invalid(
80
		GIT_REFERENCE_FORMAT_NORMAL, "refs/heads/./foo");
81
	ensure_refname_invalid(
82
		GIT_REFERENCE_FORMAT_NORMAL, "refs/heads/v@{ation");
Ben Straub committed
83 84 85 86
}

void test_refs_normalize__symbolic(void)
{
87
	ensure_refname_invalid(
88
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "");
89
	ensure_refname_invalid(
90
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "heads\foo");
91
	ensure_refname_invalid(
92
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "/");
93
	ensure_refname_invalid(
94
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "///");
95 96

	ensure_refname_normalized(
97
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "ALL_CAPS_AND_UNDERSCORES", "ALL_CAPS_AND_UNDERSCORES");
98
	ensure_refname_normalized(
99
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/MixedCasing", "refs/MixedCasing");
100
	ensure_refname_normalized(
101
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs///heads///a", "refs/heads/a");
102 103

	ensure_refname_normalized(
104
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "HEAD", "HEAD");
105
	ensure_refname_normalized(
106
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "MERGE_HEAD", "MERGE_HEAD");
107
	ensure_refname_normalized(
108
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "FETCH_HEAD", "FETCH_HEAD");
Ben Straub committed
109 110 111
}

/* Ported from JGit, BSD licence.
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
 * See https://github.com/spearce/JGit/commit/e4bf8f6957bbb29362575d641d1e77a02d906739
 *
 * Copyright (C) 2009, Google Inc.
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above
 *   copyright notice, this list of conditions and the following
 *   disclaimer in the documentation and/or other materials provided
 *   with the distribution.
 *
 * - Neither the name of the Git Development Community nor the
 *   names of its contributors may be used to endorse or promote
 *   products derived from this software without specific prior
 *   written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
149

Ben Straub committed
150 151
void test_refs_normalize__jgit_suite(void)
{
152
	/* tests borrowed from JGit */
Ben Straub committed
153 154

/* EmptyString */
155
	ensure_refname_invalid(
156
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "");
157
	ensure_refname_invalid(
158
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "/");
Ben Straub committed
159 160

/* MustHaveTwoComponents */
161
	ensure_refname_invalid(
162
		GIT_REFERENCE_FORMAT_NORMAL, "master");
163
	ensure_refname_normalized(
164
		GIT_REFERENCE_FORMAT_NORMAL, "heads/master", "heads/master");
Ben Straub committed
165 166

/* ValidHead */
167
	ensure_refname_normalized(
168
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/master", "refs/heads/master");
169
	ensure_refname_normalized(
170
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/pu", "refs/heads/pu");
171
	ensure_refname_normalized(
172
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/z", "refs/heads/z");
173
	ensure_refname_normalized(
174
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/FoO", "refs/heads/FoO");
Ben Straub committed
175 176

/* ValidTag */
177
	ensure_refname_normalized(
178
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/tags/v1.0", "refs/tags/v1.0");
Ben Straub committed
179 180

/* NoLockSuffix */
181
	ensure_refname_invalid(GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/master.lock");
Ben Straub committed
182 183

/* NoDirectorySuffix */
184
	ensure_refname_invalid(
185
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/master/");
Ben Straub committed
186 187

/* NoSpace */
188
	ensure_refname_invalid(
189
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/i haz space");
Ben Straub committed
190 191 192 193 194 195

/* NoAsciiControlCharacters */
	{
		char c;
		char buffer[GIT_REFNAME_MAX];
		for (c = '\1'; c < ' '; c++) {
196
			p_snprintf(buffer, sizeof(buffer), "refs/heads/mast%cer", c);
197
			ensure_refname_invalid(GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, buffer);
Ben Straub committed
198 199 200 201
		}
	}

/* NoBareDot */
202
	ensure_refname_invalid(
203
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/.");
204
	ensure_refname_invalid(
205
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/..");
206
	ensure_refname_invalid(
207
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/./master");
208
	ensure_refname_invalid(
209
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/../master");
Ben Straub committed
210 211

/* NoLeadingOrTrailingDot */
212
	ensure_refname_invalid(
213
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, ".");
214
	ensure_refname_invalid(
215
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/.bar");
216
	ensure_refname_invalid(
217
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/..bar");
218
	ensure_refname_invalid(
219
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/bar.");
Ben Straub committed
220 221

/* ContainsDot */
222
	ensure_refname_normalized(
223
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/m.a.s.t.e.r", "refs/heads/m.a.s.t.e.r");
224
	ensure_refname_invalid(
225
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/master..pu");
Ben Straub committed
226 227

/* NoMagicRefCharacters */
228
	ensure_refname_invalid(
229
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/master^");
230
	ensure_refname_invalid(
231
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/^master");
232
	ensure_refname_invalid(
233
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "^refs/heads/master");
234 235

	ensure_refname_invalid(
236
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/master~");
237
	ensure_refname_invalid(
238
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/~master");
239
	ensure_refname_invalid(
240
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "~refs/heads/master");
241 242

	ensure_refname_invalid(
243
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/master:");
244
	ensure_refname_invalid(
245
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/:master");
246
	ensure_refname_invalid(
247
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, ":refs/heads/master");
Ben Straub committed
248 249

/* ShellGlob */
250
	ensure_refname_invalid(
251
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/master?");
252
	ensure_refname_invalid(
253
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/?master");
254
	ensure_refname_invalid(
255
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "?refs/heads/master");
256 257

	ensure_refname_invalid(
258
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/master[");
259
	ensure_refname_invalid(
260
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/[master");
261
	ensure_refname_invalid(
262
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "[refs/heads/master");
263 264

	ensure_refname_invalid(
265
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/master*");
266
	ensure_refname_invalid(
267
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/*master");
268
	ensure_refname_invalid(
269
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "*refs/heads/master");
Ben Straub committed
270 271

/* ValidSpecialCharacters */
272
	ensure_refname_normalized
273
		(GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/!", "refs/heads/!");
274
	ensure_refname_normalized(
275
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/\"", "refs/heads/\"");
276
	ensure_refname_normalized(
277
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/#", "refs/heads/#");
278
	ensure_refname_normalized(
279
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/$", "refs/heads/$");
280
	ensure_refname_normalized(
281
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/%", "refs/heads/%");
282
	ensure_refname_normalized(
283
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/&", "refs/heads/&");
284
	ensure_refname_normalized(
285
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/'", "refs/heads/'");
286
	ensure_refname_normalized(
287
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/(", "refs/heads/(");
288
	ensure_refname_normalized(
289
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/)", "refs/heads/)");
290
	ensure_refname_normalized(
291
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/+", "refs/heads/+");
292
	ensure_refname_normalized(
293
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/,", "refs/heads/,");
294
	ensure_refname_normalized(
295
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/-", "refs/heads/-");
296
	ensure_refname_normalized(
297
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/;", "refs/heads/;");
298
	ensure_refname_normalized(
299
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/<", "refs/heads/<");
300
	ensure_refname_normalized(
301
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/=", "refs/heads/=");
302
	ensure_refname_normalized(
303
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/>", "refs/heads/>");
304
	ensure_refname_normalized(
305
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/@", "refs/heads/@");
306
	ensure_refname_normalized(
307
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/]", "refs/heads/]");
308
	ensure_refname_normalized(
309
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/_", "refs/heads/_");
310
	ensure_refname_normalized(
311
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/`", "refs/heads/`");
312
	ensure_refname_normalized(
313
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/{", "refs/heads/{");
314
	ensure_refname_normalized(
315
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/|", "refs/heads/|");
316
	ensure_refname_normalized(
317
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/}", "refs/heads/}");
Ben Straub committed
318

319 320 321 322
	/*
	 * This is valid on UNIX, but not on Windows
	 * hence we make in invalid due to non-portability
	 */
323
	ensure_refname_invalid(
324
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/\\");
Ben Straub committed
325 326 327 328

/* UnicodeNames */
	/*
	 * Currently this fails.
329
	 * ensure_refname_normalized(GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/\u00e5ngstr\u00f6m", "refs/heads/\u00e5ngstr\u00f6m");
Ben Straub committed
330 331 332
	 */

/* RefLogQueryIsValidRef */
333
	ensure_refname_invalid(
334
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/master@{1}");
335
	ensure_refname_invalid(
336
		GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "refs/heads/master@{1.hour.ago}");
337 338 339 340 341 342 343
}

void test_refs_normalize__buffer_has_to_be_big_enough_to_hold_the_normalized_version(void)
{
	char buffer_out[21];

	cl_git_pass(git_reference_normalize_name(
344
		buffer_out, 21, "refs//heads///long///name", GIT_REFERENCE_FORMAT_NORMAL));
345
	cl_git_fail(git_reference_normalize_name(
346
		buffer_out, 20, "refs//heads///long///name", GIT_REFERENCE_FORMAT_NORMAL));
Ben Straub committed
347
}
348 349

#define ONE_LEVEL_AND_REFSPEC \
350 351
	GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL \
	| GIT_REFERENCE_FORMAT_REFSPEC_PATTERN
352 353 354

void test_refs_normalize__refspec_pattern(void)
{
355 356 357 358 359 360
	ensure_refname_normalized(
		GIT_REFERENCE_FORMAT_REFSPEC_PATTERN, "heads/*foo/bar", "heads/*foo/bar");
	ensure_refname_normalized(
		GIT_REFERENCE_FORMAT_REFSPEC_PATTERN, "heads/foo*/bar", "heads/foo*/bar");
	ensure_refname_normalized(
		GIT_REFERENCE_FORMAT_REFSPEC_PATTERN, "heads/f*o/bar", "heads/f*o/bar");
361 362

	ensure_refname_invalid(
363
		GIT_REFERENCE_FORMAT_REFSPEC_PATTERN, "foo");
364
	ensure_refname_normalized(
365
		ONE_LEVEL_AND_REFSPEC, "FOO", "FOO");
366 367

	ensure_refname_normalized(
368
		GIT_REFERENCE_FORMAT_REFSPEC_PATTERN, "foo/bar", "foo/bar");
369 370 371 372
	ensure_refname_normalized(
		ONE_LEVEL_AND_REFSPEC, "foo/bar", "foo/bar");

	ensure_refname_normalized(
373
		GIT_REFERENCE_FORMAT_REFSPEC_PATTERN, "*/foo", "*/foo");
374 375 376 377
	ensure_refname_normalized(
		ONE_LEVEL_AND_REFSPEC, "*/foo", "*/foo");

	ensure_refname_normalized(
378
		GIT_REFERENCE_FORMAT_REFSPEC_PATTERN, "foo/*/bar", "foo/*/bar");
379 380 381 382
	ensure_refname_normalized(
		ONE_LEVEL_AND_REFSPEC, "foo/*/bar", "foo/*/bar");

	ensure_refname_invalid(
383
		GIT_REFERENCE_FORMAT_REFSPEC_PATTERN, "*");
384 385 386 387
	ensure_refname_normalized(
		ONE_LEVEL_AND_REFSPEC, "*", "*");

	ensure_refname_invalid(
388
		GIT_REFERENCE_FORMAT_REFSPEC_PATTERN, "foo/*/*");
389 390 391 392
	ensure_refname_invalid(
		ONE_LEVEL_AND_REFSPEC, "foo/*/*");

	ensure_refname_invalid(
393
		GIT_REFERENCE_FORMAT_REFSPEC_PATTERN, "*/foo/*");
394 395 396 397
	ensure_refname_invalid(
		ONE_LEVEL_AND_REFSPEC, "*/foo/*");

	ensure_refname_invalid(
398
		GIT_REFERENCE_FORMAT_REFSPEC_PATTERN, "*/*/foo");
399 400 401
	ensure_refname_invalid(
		ONE_LEVEL_AND_REFSPEC, "*/*/foo");
}