mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-07 20:17:59 +00:00

This converts virtually all of the places that allocate GIT_PATH_MAX buffers on the stack for manipulating paths to use git_buf objects instead. The patch is pretty careful not to touch the public API for libgit2, so there are a few places that still use GIT_PATH_MAX. This extends and changes some details of the git_buf implementation to add a couple of extra functions and to make error handling easier. This includes serious alterations to all the path.c functions, and several of the fileops.c ones, too. Also, there are a number of new functions that parallel existing ones except that use a git_buf instead of a stack-based buffer (such as git_config_find_global_r that exists alongsize git_config_find_global). This also modifies the win32 version of p_realpath to allocate whatever buffer size is needed to accommodate the realpath instead of hardcoding a GIT_PATH_MAX limit, but that change needs to be tested still.
237 lines
6.2 KiB
C
237 lines
6.2 KiB
C
#include "clay_libgit2.h"
|
|
#include <fileops.h>
|
|
|
|
static void
|
|
check_dirname(const char *A, const char *B)
|
|
{
|
|
git_buf dir = GIT_BUF_INIT;
|
|
char *dir2;
|
|
|
|
cl_assert(git_path_dirname_r(&dir, A) >= 0);
|
|
cl_assert_strequal(B, dir.ptr);
|
|
git_buf_free(&dir);
|
|
|
|
cl_assert((dir2 = git_path_dirname(A)) != NULL);
|
|
cl_assert_strequal(B, dir2);
|
|
git__free(dir2);
|
|
}
|
|
|
|
static void
|
|
check_basename(const char *A, const char *B)
|
|
{
|
|
git_buf base = GIT_BUF_INIT;
|
|
char *base2;
|
|
|
|
cl_assert(git_path_basename_r(&base, A) >= 0);
|
|
cl_assert_strequal(B, base.ptr);
|
|
git_buf_free(&base);
|
|
|
|
cl_assert((base2 = git_path_basename(A)) != NULL);
|
|
cl_assert_strequal(B, base2);
|
|
git__free(base2);
|
|
}
|
|
|
|
static void
|
|
check_topdir(const char *A, const char *B)
|
|
{
|
|
const char *dir;
|
|
|
|
cl_assert((dir = git_path_topdir(A)) != NULL);
|
|
cl_assert_strequal(B, dir);
|
|
}
|
|
|
|
static void
|
|
check_joinpath(const char *path_a, const char *path_b, const char *expected_path)
|
|
{
|
|
git_buf joined_path = GIT_BUF_INIT;
|
|
|
|
cl_git_pass(git_buf_joinpath(&joined_path, path_a, path_b));
|
|
cl_assert_strequal(expected_path, joined_path.ptr);
|
|
|
|
git_buf_free(&joined_path);
|
|
}
|
|
|
|
static void
|
|
check_joinpath_n(
|
|
const char *path_a,
|
|
const char *path_b,
|
|
const char *path_c,
|
|
const char *path_d,
|
|
const char *expected_path)
|
|
{
|
|
git_buf joined_path = GIT_BUF_INIT;
|
|
|
|
cl_git_pass(git_buf_join_n(&joined_path, '/', 4,
|
|
path_a, path_b, path_c, path_d));
|
|
cl_assert_strequal(expected_path, joined_path.ptr);
|
|
|
|
git_buf_free(&joined_path);
|
|
}
|
|
|
|
|
|
/* get the dirname of a path */
|
|
void test_core_path__0(void)
|
|
{
|
|
check_dirname(NULL, ".");
|
|
check_dirname("", ".");
|
|
check_dirname("a", ".");
|
|
check_dirname("/", "/");
|
|
check_dirname("/usr", "/");
|
|
check_dirname("/usr/", "/");
|
|
check_dirname("/usr/lib", "/usr");
|
|
check_dirname("/usr/lib/", "/usr");
|
|
check_dirname("/usr/lib//", "/usr");
|
|
check_dirname("usr/lib", "usr");
|
|
check_dirname("usr/lib/", "usr");
|
|
check_dirname("usr/lib//", "usr");
|
|
check_dirname(".git/", ".");
|
|
|
|
check_dirname(REP16("/abc"), REP15("/abc"));
|
|
}
|
|
|
|
/* get the base name of a path */
|
|
void test_core_path__1(void)
|
|
{
|
|
check_basename(NULL, ".");
|
|
check_basename("", ".");
|
|
check_basename("a", "a");
|
|
check_basename("/", "/");
|
|
check_basename("/usr", "usr");
|
|
check_basename("/usr/", "usr");
|
|
check_basename("/usr/lib", "lib");
|
|
check_basename("/usr/lib//", "lib");
|
|
check_basename("usr/lib", "lib");
|
|
|
|
check_basename(REP16("/abc"), "abc");
|
|
check_basename(REP1024("/abc"), "abc");
|
|
}
|
|
|
|
/* get the latest component in a path */
|
|
void test_core_path__2(void)
|
|
{
|
|
check_topdir(".git/", ".git/");
|
|
check_topdir("/.git/", ".git/");
|
|
check_topdir("usr/local/.git/", ".git/");
|
|
check_topdir("./.git/", ".git/");
|
|
check_topdir("/usr/.git/", ".git/");
|
|
check_topdir("/", "/");
|
|
check_topdir("a/", "a/");
|
|
|
|
cl_assert(git_path_topdir("/usr/.git") == NULL);
|
|
cl_assert(git_path_topdir(".") == NULL);
|
|
cl_assert(git_path_topdir("") == NULL);
|
|
cl_assert(git_path_topdir("a") == NULL);
|
|
}
|
|
|
|
/* properly join path components */
|
|
void test_core_path__5(void)
|
|
{
|
|
check_joinpath("", "", "");
|
|
check_joinpath("", "a", "a");
|
|
check_joinpath("", "/a", "/a");
|
|
check_joinpath("a", "", "a/");
|
|
check_joinpath("a", "/", "a/");
|
|
check_joinpath("a", "b", "a/b");
|
|
check_joinpath("/", "a", "/a");
|
|
check_joinpath("/", "", "/");
|
|
check_joinpath("/a", "/b", "/a/b");
|
|
check_joinpath("/a", "/b/", "/a/b/");
|
|
check_joinpath("/a/", "b/", "/a/b/");
|
|
check_joinpath("/a/", "/b/", "/a/b/");
|
|
|
|
check_joinpath("/abcd", "/defg", "/abcd/defg");
|
|
check_joinpath("/abcd", "/defg/", "/abcd/defg/");
|
|
check_joinpath("/abcd/", "defg/", "/abcd/defg/");
|
|
check_joinpath("/abcd/", "/defg/", "/abcd/defg/");
|
|
|
|
check_joinpath("/abcdefgh", "/12345678", "/abcdefgh/12345678");
|
|
check_joinpath("/abcdefgh", "/12345678/", "/abcdefgh/12345678/");
|
|
check_joinpath("/abcdefgh/", "12345678/", "/abcdefgh/12345678/");
|
|
|
|
check_joinpath(REP1024("aaaa"), REP1024("bbbb"),
|
|
REP1024("aaaa") "/" REP1024("bbbb"));
|
|
check_joinpath(REP1024("/aaaa"), REP1024("/bbbb"),
|
|
REP1024("/aaaa") REP1024("/bbbb"));
|
|
}
|
|
|
|
/* properly join path components for more than one path */
|
|
void test_core_path__6(void)
|
|
{
|
|
check_joinpath_n("", "", "", "", "");
|
|
check_joinpath_n("", "a", "", "", "a/");
|
|
check_joinpath_n("a", "", "", "", "a/");
|
|
check_joinpath_n("", "", "", "a", "a");
|
|
check_joinpath_n("a", "b", "", "/c/d/", "a/b/c/d/");
|
|
check_joinpath_n("a", "b", "", "/c/d", "a/b/c/d");
|
|
check_joinpath_n("abcd", "efgh", "ijkl", "mnop", "abcd/efgh/ijkl/mnop");
|
|
check_joinpath_n("abcd/", "efgh/", "ijkl/", "mnop/", "abcd/efgh/ijkl/mnop/");
|
|
check_joinpath_n("/abcd/", "/efgh/", "/ijkl/", "/mnop/", "/abcd/efgh/ijkl/mnop/");
|
|
|
|
check_joinpath_n(REP1024("a"), REP1024("b"), REP1024("c"), REP1024("d"),
|
|
REP1024("a") "/" REP1024("b") "/"
|
|
REP1024("c") "/" REP1024("d"));
|
|
check_joinpath_n(REP1024("/a"), REP1024("/b"), REP1024("/c"), REP1024("/d"),
|
|
REP1024("/a") REP1024("/b")
|
|
REP1024("/c") REP1024("/d"));
|
|
}
|
|
|
|
|
|
static void
|
|
check_path_to_dir(
|
|
const char* path,
|
|
const char* expected)
|
|
{
|
|
git_buf tgt = GIT_BUF_INIT;
|
|
|
|
git_buf_sets(&tgt, path);
|
|
cl_git_pass(git_path_to_dir(&tgt));
|
|
cl_assert_strequal(expected, tgt.ptr);
|
|
|
|
git_buf_free(&tgt);
|
|
}
|
|
|
|
static void
|
|
check_string_to_dir(
|
|
const char* path,
|
|
int maxlen,
|
|
const char* expected)
|
|
{
|
|
int len = strlen(path);
|
|
char *buf = git__malloc(len + 2);
|
|
strncpy(buf, path, len + 2);
|
|
|
|
git_path_string_to_dir(buf, maxlen);
|
|
|
|
cl_assert_strequal(expected, buf);
|
|
|
|
git__free(buf);
|
|
}
|
|
|
|
/* convert paths to dirs */
|
|
void test_core_path__7(void)
|
|
{
|
|
check_path_to_dir("", "");
|
|
check_path_to_dir(".", "./");
|
|
check_path_to_dir("./", "./");
|
|
check_path_to_dir("a/", "a/");
|
|
check_path_to_dir("ab", "ab/");
|
|
/* make sure we try just under and just over an expansion that will
|
|
* require a realloc
|
|
*/
|
|
check_path_to_dir("abcdef", "abcdef/");
|
|
check_path_to_dir("abcdefg", "abcdefg/");
|
|
check_path_to_dir("abcdefgh", "abcdefgh/");
|
|
check_path_to_dir("abcdefghi", "abcdefghi/");
|
|
check_path_to_dir(REP1024("abcd") "/", REP1024("abcd") "/");
|
|
check_path_to_dir(REP1024("abcd"), REP1024("abcd") "/");
|
|
|
|
check_string_to_dir("", 1, "");
|
|
check_string_to_dir(".", 1, ".");
|
|
check_string_to_dir(".", 2, "./");
|
|
check_string_to_dir(".", 3, "./");
|
|
check_string_to_dir("abcd", 3, "abcd");
|
|
check_string_to_dir("abcd", 4, "abcd");
|
|
check_string_to_dir("abcd", 5, "abcd/");
|
|
check_string_to_dir("abcd", 6, "abcd/");
|
|
}
|