summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/index.c3
-rw-r--r--src/refs.c9
-rw-r--r--src/util.c36
-rw-r--r--src/util.h22
-rw-r--r--tests/t00-core.c22
-rw-r--r--tests/t10-refs.c50
6 files changed, 59 insertions, 83 deletions
diff --git a/src/index.c b/src/index.c
index 6fdb46e18..0e77105b8 100644
--- a/src/index.c
+++ b/src/index.c
@@ -289,8 +289,7 @@ int git_index_add(git_index *index, const char *rel_path, int stage)
if (index->repository == NULL)
return GIT_EBAREINDEX;
- strcpy(full_path, index->repository->path_workdir);
- strcat(full_path, rel_path);
+ git__joinpath(full_path, index->repository->path_workdir, rel_path);
if (gitfo_exists(full_path) < 0)
return GIT_ENOTFOUND;
diff --git a/src/refs.c b/src/refs.c
index eca50ddaa..a3055650f 100644
--- a/src/refs.c
+++ b/src/refs.c
@@ -159,8 +159,7 @@ static int read_loose_ref(gitfo_buf *file_content, const char *name, const char
char ref_path[GIT_PATH_MAX];
/* Determine the full path of the ref */
- strcpy(ref_path, repo_path);
- strcat(ref_path, name);
+ git__joinpath(ref_path, repo_path, name);
/* Does it even exist ? */
if (gitfo_exists(ref_path) < GIT_SUCCESS)
@@ -228,8 +227,7 @@ static int read_packed_refs(gitfo_buf *packfile, const char *repo_path)
char ref_path[GIT_PATH_MAX];
/* Determine the full path of the file */
- strcpy(ref_path, repo_path);
- strcat(ref_path, GIT_PACKEDREFS_FILE);
+ git__joinpath(ref_path, repo_path, GIT_PACKEDREFS_FILE);
/* Does it even exist ? */
if (gitfo_exists(ref_path) < GIT_SUCCESS)
@@ -528,8 +526,7 @@ int git_reference_write(git_reference *ref)
if ((error = check_refname(ref->name)) < GIT_SUCCESS)
return error;
- strcpy(ref_path, ref->owner->path_repository);
- strcat(ref_path, ref->name);
+ git__joinpath(ref_path, ref->owner->path_repository, ref->name);
if ((error = git_filelock_init(&lock, ref_path)) < GIT_SUCCESS)
goto error_cleanup;
diff --git a/src/util.c b/src/util.c
index 67b74eeba..fc1682f90 100644
--- a/src/util.c
+++ b/src/util.c
@@ -202,30 +202,30 @@ const char *git__topdir(const char *path)
return &path[i + 1];
}
-char *git__joinpath(const char *path_a, const char *path_b)
+void git__joinpath_n(char *buffer_out, int count, ...)
{
- int len_a, len_b;
- char *path_new;
-
- assert(path_a && path_b);
+ va_list ap;
+ int i;
- len_a = strlen(path_a);
- len_b = strlen(path_b);
+ va_start(ap, count);
+ for (i = 0; i < count; ++i) {
+ const char *path;
+ int len;
- path_new = git__malloc(len_a + len_b + 2);
- if (path_new == NULL)
- return NULL;
+ path = va_arg(ap, const char *);
+ if (i > 0 && *path == '/')
+ path++;
- strcpy(path_new, path_a);
+ len = strlen(path);
+ memcpy(buffer_out, path, len);
+ buffer_out = buffer_out + len;
- if (len_a > 0 && len_b > 0 && path_new[len_a - 1] != '/')
- path_new[len_a++] = '/';
-
- if (path_b[0] == '/')
- path_b++;
+ if (i < count - 1 && buffer_out[-1] != '/')
+ *buffer_out++ = '/';
+ }
+ va_end(ap);
- strcpy(path_new + len_a, path_b);
- return path_new;
+ *buffer_out = '\0';
}
static char *strtok_raw(char *output, char *src, char *delimit, int keep)
diff --git a/src/util.h b/src/util.h
index 0f010929f..d5320e15b 100644
--- a/src/util.h
+++ b/src/util.h
@@ -62,9 +62,15 @@ extern const char *git__topdir(const char *path);
* Join two paths together. Takes care of properly fixing the
* middle slashes and everything
*
- * Returns a newly allocated string; must be free'd manually.
+ * The paths are joined together into buffer_out; this is expected
+ * to be an user allocated buffer of `GIT_PATH_MAX` size
*/
-extern char *git__joinpath(const char *path_a, const char *path_b);
+extern void git__joinpath_n(char *buffer_out, int npath, ...);
+
+GIT_INLINE(void) git__joinpath(char *buffer_out, const char *path_a, const char *path_b)
+{
+ git__joinpath_n(buffer_out, 2, path_a, path_b);
+}
extern void git__hexdump(const char *buffer, size_t n);
extern uint32_t git__hash(const void *key, int len, uint32_t seed);
@@ -84,18 +90,6 @@ GIT_INLINE(int) git__is_sizet(git_off_t p)
# define git__rotl(v, s) (uint32_t)(((uint32_t)(v) << (s)) | ((uint32_t)(v) >> (32 - (s))))
#endif
-enum git_splitpath_flags
-{
- GIT_SPL_PATH = 1,
- GIT_SPL_FILE = 2,
- GIT_SPL_EXT = 4,
- GIT_SPL_PATH_FILE = GIT_SPL_PATH + GIT_SPL_FILE,
- GIT_SPL_FILE_EXT = GIT_SPL_FILE + GIT_SPL_EXT,
- GIT_SPL_EXT_NO_PERIOD = 8,
-};
-
-
-extern char *git__splitpath(char *path, int flag);
extern char *git__strtok(char *output, char *src, char *delimit);
extern char *git__strtok_keep(char *output, char *src, char *delimit);
diff --git a/tests/t00-core.c b/tests/t00-core.c
index f20aa9d76..96bf3e772 100644
--- a/tests/t00-core.c
+++ b/tests/t00-core.c
@@ -344,25 +344,15 @@ END_TEST
static int ensure_joinpath(const char *path_a, const char *path_b, const char *expected_path)
{
- int error = GIT_SUCCESS;
- char* joined_path;
-
- joined_path = git__joinpath(path_a, path_b);
- if (joined_path == NULL)
- return GIT_ERROR;
-
- if (strcmp(joined_path, expected_path))
- error = GIT_ERROR;
-
- free(joined_path);
-
- return error;
+ char joined_path[GIT_PATH_MAX];
+ git__joinpath(joined_path, path_a, path_b);
+ return strcmp(joined_path, expected_path) == 0 ? GIT_SUCCESS : GIT_ERROR;
}
BEGIN_TEST("path", joinpath)
- must_pass(ensure_joinpath("", "", ""));
- must_pass(ensure_joinpath("", "a", "a"));
- must_pass(ensure_joinpath("a", "", "a"));
+ must_pass(ensure_joinpath("", "", "/"));
+ must_pass(ensure_joinpath("", "a", "/a"));
+ must_pass(ensure_joinpath("a", "", "a/"));
must_pass(ensure_joinpath("a", "b", "a/b"));
must_pass(ensure_joinpath("/", "a", "/a"));
must_pass(ensure_joinpath("/", "", "/"));
diff --git a/tests/t10-refs.c b/tests/t10-refs.c
index 222f09997..2d055c978 100644
--- a/tests/t10-refs.c
+++ b/tests/t10-refs.c
@@ -192,7 +192,7 @@ BEGIN_TEST("createref", create_new_symbolic_ref)
git_reference *new_reference, *looked_up_ref, *resolved_ref;
git_repository *repo;
git_oid id;
- char *ref_path;
+ char ref_path[GIT_PATH_MAX];
const char *new_head_tracker = "another-head-tracker";
@@ -201,8 +201,7 @@ BEGIN_TEST("createref", create_new_symbolic_ref)
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
/* Retrieve the physical path to the symbolic ref for further cleaning */
- ref_path = git__joinpath(repo->path_repository, new_head_tracker);
- must_be_true(ref_path != NULL);
+ git__joinpath(ref_path, repo->path_repository, new_head_tracker);
/* Create and write the new symbolic reference */
must_pass(git_reference_new(&new_reference, repo));
@@ -211,16 +210,16 @@ BEGIN_TEST("createref", create_new_symbolic_ref)
must_pass(git_reference_write(new_reference));
/* Ensure the reference can be looked-up... */
- must_pass(git_repository_lookup_ref(&looked_up_ref, repo, new_head_tracker));
- must_be_true(looked_up_ref->type == GIT_REF_SYMBOLIC);
- must_be_true(looked_up_ref->packed == 0);
- must_be_true(strcmp(looked_up_ref->name, new_head_tracker) == 0);
-
- /* ...peeled.. */
- must_pass(git_reference_resolve(&resolved_ref, looked_up_ref));
- must_be_true(resolved_ref->type == GIT_REF_OID);
-
- /* ...and that it points to the current master tip */
+ must_pass(git_repository_lookup_ref(&looked_up_ref, repo, new_head_tracker));
+ must_be_true(looked_up_ref->type == GIT_REF_SYMBOLIC);
+ must_be_true(looked_up_ref->packed == 0);
+ must_be_true(strcmp(looked_up_ref->name, new_head_tracker) == 0);
+
+ /* ...peeled.. */
+ must_pass(git_reference_resolve(&resolved_ref, looked_up_ref));
+ must_be_true(resolved_ref->type == GIT_REF_OID);
+
+ /* ...and that it points to the current master tip */
must_be_true(git_oid_cmp(&id, git_reference_oid(resolved_ref)) == 0);
git_repository_free(repo);
@@ -228,21 +227,20 @@ BEGIN_TEST("createref", create_new_symbolic_ref)
/* Similar test with a fresh new repository */
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
- must_pass(git_repository_lookup_ref(&looked_up_ref, repo, new_head_tracker));
- must_pass(git_reference_resolve(&resolved_ref, looked_up_ref));
+ must_pass(git_repository_lookup_ref(&looked_up_ref, repo, new_head_tracker));
+ must_pass(git_reference_resolve(&resolved_ref, looked_up_ref));
must_be_true(git_oid_cmp(&id, git_reference_oid(resolved_ref)) == 0);
git_repository_free(repo);
must_pass(gitfo_unlink(ref_path)); /* TODO: replace with git_reference_delete() when available */
- free(ref_path);
END_TEST
BEGIN_TEST("createref", create_new_object_id_ref)
git_reference *new_reference, *looked_up_ref;
git_repository *repo;
git_oid id;
- char *ref_path;
+ char ref_path[GIT_PATH_MAX];
const char *new_head = "refs/heads/new-head";
@@ -251,8 +249,7 @@ BEGIN_TEST("createref", create_new_object_id_ref)
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
/* Retrieve the physical path to the symbolic ref for further cleaning */
- ref_path = git__joinpath(repo->path_repository, new_head);
- must_be_true(ref_path != NULL);
+ git__joinpath(ref_path, repo->path_repository, new_head);
/* Create and write the new object id reference */
must_pass(git_reference_new(&new_reference, repo));
@@ -261,12 +258,12 @@ BEGIN_TEST("createref", create_new_object_id_ref)
must_pass(git_reference_write(new_reference));
/* Ensure the reference can be looked-up... */
- must_pass(git_repository_lookup_ref(&looked_up_ref, repo, new_head));
- must_be_true(looked_up_ref->type == GIT_REF_OID);
- must_be_true(looked_up_ref->packed == 0);
- must_be_true(strcmp(looked_up_ref->name, new_head) == 0);
-
- /* ...and that it points to the current master tip */
+ must_pass(git_repository_lookup_ref(&looked_up_ref, repo, new_head));
+ must_be_true(looked_up_ref->type == GIT_REF_OID);
+ must_be_true(looked_up_ref->packed == 0);
+ must_be_true(strcmp(looked_up_ref->name, new_head) == 0);
+
+ /* ...and that it points to the current master tip */
must_be_true(git_oid_cmp(&id, git_reference_oid(looked_up_ref)) == 0);
git_repository_free(repo);
@@ -274,13 +271,12 @@ BEGIN_TEST("createref", create_new_object_id_ref)
/* Similar test with a fresh new repository */
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
- must_pass(git_repository_lookup_ref(&looked_up_ref, repo, new_head));
+ must_pass(git_repository_lookup_ref(&looked_up_ref, repo, new_head));
must_be_true(git_oid_cmp(&id, git_reference_oid(looked_up_ref)) == 0);
git_repository_free(repo);
must_pass(gitfo_unlink(ref_path)); /* TODO: replace with git_reference_delete() when available */
- free(ref_path);
END_TEST
git_testsuite *libgit2_suite_refs(void)