Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e8909d5

Browse files
ethomsonEdward Thomson
authored and
Edward Thomson
committed
git_path_join_unrooted: return base len
The documentation for `git_path_join_unrooted` states that the base length will be returned, so that consumers like checkout know where to start creating directories instead of always creating directories at the directory root.
1 parent 651afd0 commit e8909d5

File tree

4 files changed

+81
-15
lines changed

4 files changed

+81
-15
lines changed

src/checkout.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1069,7 +1069,7 @@ static int checkout_conflicts_mark_directoryfile(
10691069
goto done;
10701070
}
10711071

1072-
prefixed = git_path_equal_or_prefixed(path, entry->path);
1072+
prefixed = git_path_equal_or_prefixed(path, entry->path, NULL);
10731073

10741074
if (prefixed == GIT_PATH_EQUAL)
10751075
continue;

src/path.c

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -263,26 +263,31 @@ int git_path_root(const char *path)
263263
int git_path_join_unrooted(
264264
git_buf *path_out, const char *path, const char *base, ssize_t *root_at)
265265
{
266-
int error, root;
266+
ssize_t root;
267267

268268
assert(path && path_out);
269269

270-
root = git_path_root(path);
270+
root = (ssize_t)git_path_root(path);
271271

272272
if (base != NULL && root < 0) {
273-
error = git_buf_joinpath(path_out, base, path);
273+
if (git_buf_joinpath(path_out, base, path) < 0)
274+
return -1;
274275

275-
if (root_at)
276-
*root_at = (ssize_t)strlen(base);
277-
}
278-
else {
279-
error = git_buf_sets(path_out, path);
276+
root = (ssize_t)strlen(base);
277+
} else {
278+
if (git_buf_sets(path_out, path) < 0)
279+
return -1;
280280

281-
if (root_at)
282-
*root_at = (root < 0) ? 0 : (ssize_t)root;
281+
if (root < 0)
282+
root = 0;
283+
else if (base)
284+
git_path_equal_or_prefixed(base, path, &root);
283285
}
284286

285-
return error;
287+
if (root_at)
288+
*root_at = root;
289+
290+
return 0;
286291
}
287292

288293
int git_path_prettify(git_buf *path_out, const char *path, const char *base)

src/path.h

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -396,21 +396,35 @@ enum { GIT_PATH_NOTEQUAL = 0, GIT_PATH_EQUAL = 1, GIT_PATH_PREFIX = 2 };
396396
*/
397397
GIT_INLINE(int) git_path_equal_or_prefixed(
398398
const char *parent,
399-
const char *child)
399+
const char *child,
400+
ssize_t *prefixlen)
400401
{
401402
const char *p = parent, *c = child;
403+
int lastslash = 0;
402404

403405
while (*p && *c) {
406+
lastslash = (*p == '/');
407+
404408
if (*p++ != *c++)
405409
return GIT_PATH_NOTEQUAL;
406410
}
407411

408412
if (*p != '\0')
409413
return GIT_PATH_NOTEQUAL;
410-
if (*c == '\0')
414+
415+
if (*c == '\0') {
416+
if (prefixlen)
417+
*prefixlen = p - parent;
418+
411419
return GIT_PATH_EQUAL;
412-
if (*c == '/')
420+
}
421+
422+
if (*c == '/' || lastslash) {
423+
if (prefixlen)
424+
*prefixlen = (p - parent) - lastslash;
425+
413426
return GIT_PATH_PREFIX;
427+
}
414428

415429
return GIT_PATH_NOTEQUAL;
416430
}

tests/path/core.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,3 +290,50 @@ void test_path_core__isvalid_dotgit_with_hfs_ignorables(void)
290290
cl_assert_equal_b(true, git_path_isvalid(NULL, ".git\xe2\x80\xbf", GIT_PATH_REJECT_DOT_GIT_HFS));
291291
cl_assert_equal_b(true, git_path_isvalid(NULL, ".git\xe2\xab\x81", GIT_PATH_REJECT_DOT_GIT_HFS));
292292
}
293+
294+
static void test_join_unrooted(
295+
const char *expected_result,
296+
ssize_t expected_rootlen,
297+
const char *path,
298+
const char *base)
299+
{
300+
git_buf result = GIT_BUF_INIT;
301+
ssize_t root_at;
302+
303+
cl_git_pass(git_path_join_unrooted(&result, path, base, &root_at));
304+
cl_assert_equal_s(expected_result, result.ptr);
305+
cl_assert_equal_i(expected_rootlen, root_at);
306+
307+
git_buf_free(&result);
308+
}
309+
310+
void test_path_core__join_unrooted(void)
311+
{
312+
git_buf out = GIT_BUF_INIT;
313+
314+
test_join_unrooted("foo", 0, "foo", NULL);
315+
test_join_unrooted("foo/bar", 0, "foo/bar", NULL);
316+
317+
/* Relative paths have base prepended */
318+
test_join_unrooted("/foo/bar", 4, "bar", "/foo");
319+
test_join_unrooted("/foo/bar/foobar", 4, "bar/foobar", "/foo");
320+
test_join_unrooted("c:/foo/bar/foobar", 6, "bar/foobar", "c:/foo");
321+
test_join_unrooted("c:/foo/bar/foobar", 10, "foobar", "c:/foo/bar");
322+
323+
/* Absolute paths are not prepended with base */
324+
test_join_unrooted("/foo", 0, "/foo", "/asdf");
325+
test_join_unrooted("/foo/bar", 0, "/foo/bar", "/asdf");
326+
327+
/* Drive letter is given as root length on Windows */
328+
test_join_unrooted("c:/foo", 2, "c:/foo", "c:/asdf");
329+
test_join_unrooted("c:/foo/bar", 2, "c:/foo/bar", "c:/asdf");
330+
331+
/* Base is returned when it's provided and is the prefix */
332+
test_join_unrooted("c:/foo/bar/foobar", 6, "c:/foo/bar/foobar", "c:/foo");
333+
test_join_unrooted("c:/foo/bar/foobar", 10, "c:/foo/bar/foobar", "c:/foo/bar");
334+
335+
/* Trailing slash in the base is ignored */
336+
test_join_unrooted("c:/foo/bar/foobar", 6, "c:/foo/bar/foobar", "c:/foo/");
337+
338+
git_buf_free(&out);
339+
}

0 commit comments

Comments
 (0)