Commit 7a3bd1e7 by Carlos Martín Nieto

repository: move to use a git_buf for outputting strings

Since we now export that type, we can avoid making the user guess a
size.
parent 1087d4fd
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "common.h" #include "common.h"
#include "types.h" #include "types.h"
#include "oid.h" #include "oid.h"
#include "buffer.h"
/** /**
* @file git2/repository.h * @file git2/repository.h
...@@ -58,10 +59,8 @@ GIT_EXTERN(int) git_repository_wrap_odb(git_repository **out, git_odb *odb); ...@@ -58,10 +59,8 @@ GIT_EXTERN(int) git_repository_wrap_odb(git_repository **out, git_odb *odb);
* The method will automatically detect if the repository is bare * The method will automatically detect if the repository is bare
* (if there is a repository). * (if there is a repository).
* *
* @param path_out The user allocated buffer which will * @param out A pointer to a user-allocated git_buf which will contain
* contain the found path. * the found path.
*
* @param path_size repository_path size
* *
* @param start_path The base path where the lookup starts. * @param start_path The base path where the lookup starts.
* *
...@@ -77,8 +76,7 @@ GIT_EXTERN(int) git_repository_wrap_odb(git_repository **out, git_odb *odb); ...@@ -77,8 +76,7 @@ GIT_EXTERN(int) git_repository_wrap_odb(git_repository **out, git_odb *odb);
* @return 0 or an error code * @return 0 or an error code
*/ */
GIT_EXTERN(int) git_repository_discover( GIT_EXTERN(int) git_repository_discover(
char *path_out, git_buf *out,
size_t path_size,
const char *start_path, const char *start_path,
int across_fs, int across_fs,
const char *ceiling_dirs); const char *ceiling_dirs);
...@@ -464,21 +462,11 @@ GIT_EXTERN(int) git_repository_index(git_index **out, git_repository *repo); ...@@ -464,21 +462,11 @@ GIT_EXTERN(int) git_repository_index(git_index **out, git_repository *repo);
* Use this function to get the contents of this file. Don't forget to * Use this function to get the contents of this file. Don't forget to
* remove the file after you create the commit. * remove the file after you create the commit.
* *
* If the repository message exists and there are no errors reading it, this * @param out git_buf to write data into
* returns the bytes needed to store the message in memory (i.e. message
* file size plus one terminating NUL byte). That value is returned even if
* `out` is NULL or `len` is shorter than the necessary size.
*
* The `out` buffer will *always* be NUL terminated, even if truncation
* occurs.
*
* @param out Buffer to write data into or NULL to just read required size
* @param len Length of `out` buffer in bytes
* @param repo Repository to read prepared message from * @param repo Repository to read prepared message from
* @return GIT_ENOTFOUND if no message exists, other value < 0 for other * @return 0, GIT_ENOTFOUND if no message exists or an error code
* errors, or total bytes in message (may be > `len`) on success
*/ */
GIT_EXTERN(int) git_repository_message(char *out, size_t len, git_repository *repo); GIT_EXTERN(int) git_repository_message(git_buf *out, git_repository *repo);
/** /**
* Remove git's prepared message. * Remove git's prepared message.
......
...@@ -495,34 +495,18 @@ int git_repository_wrap_odb(git_repository **repo_out, git_odb *odb) ...@@ -495,34 +495,18 @@ int git_repository_wrap_odb(git_repository **repo_out, git_odb *odb)
} }
int git_repository_discover( int git_repository_discover(
char *repository_path, git_buf *out,
size_t size,
const char *start_path, const char *start_path,
int across_fs, int across_fs,
const char *ceiling_dirs) const char *ceiling_dirs)
{ {
git_buf path = GIT_BUF_INIT;
uint32_t flags = across_fs ? GIT_REPOSITORY_OPEN_CROSS_FS : 0; uint32_t flags = across_fs ? GIT_REPOSITORY_OPEN_CROSS_FS : 0;
int error;
assert(start_path && repository_path && size > 0);
*repository_path = '\0';
if ((error = find_repo(&path, NULL, start_path, flags, ceiling_dirs)) < 0) assert(start_path);
return error != GIT_ENOTFOUND ? -1 : error;
if (size < (size_t)(path.size + 1)) { git_buf_sanitize(out);
giterr_set(GITERR_REPOSITORY,
"The given buffer is too small to store the discovered path");
git_buf_free(&path);
return -1;
}
/* success: we discovered a repository */ return find_repo(out, NULL, start_path, flags, ceiling_dirs);
git_buf_copy_cstr(repository_path, size, &path);
git_buf_free(&path);
return 0;
} }
static int load_config( static int load_config(
...@@ -1732,14 +1716,13 @@ cleanup: ...@@ -1732,14 +1716,13 @@ cleanup:
return error; return error;
} }
int git_repository_message(char *buffer, size_t len, git_repository *repo) int git_repository_message(git_buf *out, git_repository *repo)
{ {
git_buf buf = GIT_BUF_INIT, path = GIT_BUF_INIT; git_buf path = GIT_BUF_INIT;
struct stat st; struct stat st;
int error; int error;
if (buffer != NULL) git_buf_sanitize(out);
*buffer = '\0';
if (git_buf_joinpath(&path, repo->path_repository, GIT_MERGE_MSG_FILE) < 0) if (git_buf_joinpath(&path, repo->path_repository, GIT_MERGE_MSG_FILE) < 0)
return -1; return -1;
...@@ -1749,16 +1732,10 @@ int git_repository_message(char *buffer, size_t len, git_repository *repo) ...@@ -1749,16 +1732,10 @@ int git_repository_message(char *buffer, size_t len, git_repository *repo)
error = GIT_ENOTFOUND; error = GIT_ENOTFOUND;
giterr_set(GITERR_OS, "Could not access message file"); giterr_set(GITERR_OS, "Could not access message file");
} }
else if (buffer != NULL) {
error = git_futils_readbuffer(&buf, git_buf_cstr(&path));
git_buf_copy_cstr(buffer, len, &buf);
}
git_buf_free(&path); error = git_futils_readbuffer(out, git_buf_cstr(&path));
git_buf_free(&buf);
if (!error) git_buf_free(&path);
error = (int)st.st_size + 1; /* add 1 for NUL byte */
return error; return error;
} }
......
...@@ -25,12 +25,13 @@ ...@@ -25,12 +25,13 @@
static void ensure_repository_discover(const char *start_path, static void ensure_repository_discover(const char *start_path,
const char *ceiling_dirs, const char *ceiling_dirs,
const char *expected_path) git_buf *expected_path)
{ {
char found_path[GIT_PATH_MAX]; git_buf found_path = GIT_BUF_INIT;
cl_git_pass(git_repository_discover(found_path, sizeof(found_path), start_path, 0, ceiling_dirs)); cl_git_pass(git_repository_discover(&found_path, start_path, 0, ceiling_dirs));
//across_fs is always 0 as we can't automate the filesystem change tests //across_fs is always 0 as we can't automate the filesystem change tests
cl_assert_equal_s(found_path, expected_path); cl_assert_equal_s(found_path.ptr, expected_path->ptr);
git_buf_free(&found_path);
} }
static void write_file(const char *path, const char *content) static void write_file(const char *path, const char *content)
...@@ -69,42 +70,40 @@ static void append_ceiling_dir(git_buf *ceiling_dirs, const char *path) ...@@ -69,42 +70,40 @@ static void append_ceiling_dir(git_buf *ceiling_dirs, const char *path)
void test_repo_discover__0(void) void test_repo_discover__0(void)
{ {
// test discover // test discover
git_repository *repo; git_repository *repo;
git_buf ceiling_dirs_buf = GIT_BUF_INIT; git_buf ceiling_dirs_buf = GIT_BUF_INIT, repository_path = GIT_BUF_INIT,
sub_repository_path = GIT_BUF_INIT, found_path = GIT_BUF_INIT;
const char *ceiling_dirs; const char *ceiling_dirs;
char repository_path[GIT_PATH_MAX];
char sub_repository_path[GIT_PATH_MAX];
char found_path[GIT_PATH_MAX];
const mode_t mode = 0777; const mode_t mode = 0777;
git_futils_mkdir_r(DISCOVER_FOLDER, NULL, mode); git_futils_mkdir_r(DISCOVER_FOLDER, NULL, mode);
append_ceiling_dir(&ceiling_dirs_buf, TEMP_REPO_FOLDER); append_ceiling_dir(&ceiling_dirs_buf, TEMP_REPO_FOLDER);
ceiling_dirs = git_buf_cstr(&ceiling_dirs_buf); ceiling_dirs = git_buf_cstr(&ceiling_dirs_buf);
cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(repository_path, sizeof(repository_path), DISCOVER_FOLDER, 0, ceiling_dirs)); cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&repository_path, DISCOVER_FOLDER, 0, ceiling_dirs));
cl_git_pass(git_repository_init(&repo, DISCOVER_FOLDER, 1)); cl_git_pass(git_repository_init(&repo, DISCOVER_FOLDER, 1));
cl_git_pass(git_repository_discover(repository_path, sizeof(repository_path), DISCOVER_FOLDER, 0, ceiling_dirs)); cl_git_pass(git_repository_discover(&repository_path, DISCOVER_FOLDER, 0, ceiling_dirs));
git_repository_free(repo); git_repository_free(repo);
cl_git_pass(git_repository_init(&repo, SUB_REPOSITORY_FOLDER, 0)); cl_git_pass(git_repository_init(&repo, SUB_REPOSITORY_FOLDER, 0));
cl_git_pass(git_futils_mkdir_r(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, NULL, mode)); cl_git_pass(git_futils_mkdir_r(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, NULL, mode));
cl_git_pass(git_repository_discover(sub_repository_path, sizeof(sub_repository_path), SUB_REPOSITORY_FOLDER, 0, ceiling_dirs)); cl_git_pass(git_repository_discover(&sub_repository_path, SUB_REPOSITORY_FOLDER, 0, ceiling_dirs));
cl_git_pass(git_futils_mkdir_r(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, NULL, mode)); cl_git_pass(git_futils_mkdir_r(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, NULL, mode));
ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB, ceiling_dirs, sub_repository_path); ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB, ceiling_dirs, &sub_repository_path);
ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB_SUB, ceiling_dirs, sub_repository_path); ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB_SUB, ceiling_dirs, &sub_repository_path);
ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, ceiling_dirs, sub_repository_path); ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, ceiling_dirs, &sub_repository_path);
cl_git_pass(git_futils_mkdir_r(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, NULL, mode)); cl_git_pass(git_futils_mkdir_r(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, NULL, mode));
write_file(REPOSITORY_ALTERNATE_FOLDER "/" DOT_GIT, "gitdir: ../" SUB_REPOSITORY_FOLDER_NAME "/" DOT_GIT); write_file(REPOSITORY_ALTERNATE_FOLDER "/" DOT_GIT, "gitdir: ../" SUB_REPOSITORY_FOLDER_NAME "/" DOT_GIT);
write_file(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB "/" DOT_GIT, "gitdir: ../../../" SUB_REPOSITORY_FOLDER_NAME "/" DOT_GIT); write_file(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB "/" DOT_GIT, "gitdir: ../../../" SUB_REPOSITORY_FOLDER_NAME "/" DOT_GIT);
write_file(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB "/" DOT_GIT, "gitdir: ../../../../"); write_file(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB "/" DOT_GIT, "gitdir: ../../../../");
ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER, ceiling_dirs, sub_repository_path); ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER, ceiling_dirs, &sub_repository_path);
ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB, ceiling_dirs, sub_repository_path); ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB, ceiling_dirs, &sub_repository_path);
ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB, ceiling_dirs, sub_repository_path); ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB, ceiling_dirs, &sub_repository_path);
ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, ceiling_dirs, repository_path); ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, ceiling_dirs, &repository_path);
cl_git_pass(git_futils_mkdir_r(ALTERNATE_MALFORMED_FOLDER1, NULL, mode)); cl_git_pass(git_futils_mkdir_r(ALTERNATE_MALFORMED_FOLDER1, NULL, mode));
write_file(ALTERNATE_MALFORMED_FOLDER1 "/" DOT_GIT, "Anything but not gitdir:"); write_file(ALTERNATE_MALFORMED_FOLDER1 "/" DOT_GIT, "Anything but not gitdir:");
...@@ -114,29 +113,31 @@ void test_repo_discover__0(void) ...@@ -114,29 +113,31 @@ void test_repo_discover__0(void)
write_file(ALTERNATE_MALFORMED_FOLDER3 "/" DOT_GIT, "gitdir: \n\n\n"); write_file(ALTERNATE_MALFORMED_FOLDER3 "/" DOT_GIT, "gitdir: \n\n\n");
cl_git_pass(git_futils_mkdir_r(ALTERNATE_NOT_FOUND_FOLDER, NULL, mode)); cl_git_pass(git_futils_mkdir_r(ALTERNATE_NOT_FOUND_FOLDER, NULL, mode));
write_file(ALTERNATE_NOT_FOUND_FOLDER "/" DOT_GIT, "gitdir: a_repository_that_surely_does_not_exist"); write_file(ALTERNATE_NOT_FOUND_FOLDER "/" DOT_GIT, "gitdir: a_repository_that_surely_does_not_exist");
cl_git_fail(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_MALFORMED_FOLDER1, 0, ceiling_dirs)); cl_git_fail(git_repository_discover(&found_path, ALTERNATE_MALFORMED_FOLDER1, 0, ceiling_dirs));
cl_git_fail(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_MALFORMED_FOLDER2, 0, ceiling_dirs)); cl_git_fail(git_repository_discover(&found_path, ALTERNATE_MALFORMED_FOLDER2, 0, ceiling_dirs));
cl_git_fail(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_MALFORMED_FOLDER3, 0, ceiling_dirs)); cl_git_fail(git_repository_discover(&found_path, ALTERNATE_MALFORMED_FOLDER3, 0, ceiling_dirs));
cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(found_path, sizeof(found_path), ALTERNATE_NOT_FOUND_FOLDER, 0, ceiling_dirs)); cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&found_path, ALTERNATE_NOT_FOUND_FOLDER, 0, ceiling_dirs));
append_ceiling_dir(&ceiling_dirs_buf, SUB_REPOSITORY_FOLDER); append_ceiling_dir(&ceiling_dirs_buf, SUB_REPOSITORY_FOLDER);
ceiling_dirs = git_buf_cstr(&ceiling_dirs_buf); ceiling_dirs = git_buf_cstr(&ceiling_dirs_buf);
//this must pass as ceiling_directories cannot predent the current //this must pass as ceiling_directories cannot predent the current
//working directory to be checked //working directory to be checked
cl_git_pass(git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER, 0, ceiling_dirs)); cl_git_pass(git_repository_discover(&found_path, SUB_REPOSITORY_FOLDER, 0, ceiling_dirs));
cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB, 0, ceiling_dirs)); cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&found_path, SUB_REPOSITORY_FOLDER_SUB, 0, ceiling_dirs));
cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB_SUB, 0, ceiling_dirs)); cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&found_path, SUB_REPOSITORY_FOLDER_SUB_SUB, 0, ceiling_dirs));
cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, 0, ceiling_dirs)); cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&found_path, SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, 0, ceiling_dirs));
//.gitfile redirection should not be affected by ceiling directories //.gitfile redirection should not be affected by ceiling directories
ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER, ceiling_dirs, sub_repository_path); ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER, ceiling_dirs, &sub_repository_path);
ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB, ceiling_dirs, sub_repository_path); ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB, ceiling_dirs, &sub_repository_path);
ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB, ceiling_dirs, sub_repository_path); ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB, ceiling_dirs, &sub_repository_path);
ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, ceiling_dirs, repository_path); ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, ceiling_dirs, &repository_path);
cl_git_pass(git_futils_rmdir_r(TEMP_REPO_FOLDER, NULL, GIT_RMDIR_REMOVE_FILES)); cl_git_pass(git_futils_rmdir_r(TEMP_REPO_FOLDER, NULL, GIT_RMDIR_REMOVE_FILES));
git_repository_free(repo); git_repository_free(repo);
git_buf_free(&ceiling_dirs_buf); git_buf_free(&ceiling_dirs_buf);
git_buf_free(&repository_path);
git_buf_free(&sub_repository_path);
} }
...@@ -5,48 +5,37 @@ ...@@ -5,48 +5,37 @@
static git_repository *_repo; static git_repository *_repo;
static git_buf _path; static git_buf _path;
static char *_actual; static git_buf _actual;
void test_repo_message__initialize(void) void test_repo_message__initialize(void)
{ {
_repo = cl_git_sandbox_init("testrepo.git"); _repo = cl_git_sandbox_init("testrepo.git");
git_buf_init(&_actual, 0);
} }
void test_repo_message__cleanup(void) void test_repo_message__cleanup(void)
{ {
cl_git_sandbox_cleanup(); cl_git_sandbox_cleanup();
git_buf_free(&_path); git_buf_free(&_path);
git__free(_actual); git_buf_free(&_actual);
_actual = NULL;
} }
void test_repo_message__none(void) void test_repo_message__none(void)
{ {
cl_assert_equal_i(GIT_ENOTFOUND, git_repository_message(NULL, 0, _repo)); cl_assert_equal_i(GIT_ENOTFOUND, git_repository_message(&_actual, _repo));
} }
void test_repo_message__message(void) void test_repo_message__message(void)
{ {
const char expected[] = "Test\n\nThis is a test of the emergency broadcast system\n"; const char expected[] = "Test\n\nThis is a test of the emergency broadcast system\n";
ssize_t len;
cl_git_pass(git_buf_joinpath(&_path, git_repository_path(_repo), "MERGE_MSG")); cl_git_pass(git_buf_joinpath(&_path, git_repository_path(_repo), "MERGE_MSG"));
cl_git_mkfile(git_buf_cstr(&_path), expected); cl_git_mkfile(git_buf_cstr(&_path), expected);
len = git_repository_message(NULL, 0, _repo); cl_git_pass(git_repository_message(&_actual, _repo));
cl_assert(len > 0);
_actual = git__malloc(len + 1);
cl_assert(_actual != NULL);
/* Test non truncation */
cl_assert(git_repository_message(_actual, len, _repo) > 0);
cl_assert_equal_s(expected, _actual); cl_assert_equal_s(expected, _actual);
git_buf_free(&_actual);
/* Test truncation and that trailing NUL is inserted */
cl_assert(git_repository_message(_actual, 6, _repo) > 0);
cl_assert_equal_s("Test\n", _actual);
cl_git_pass(p_unlink(git_buf_cstr(&_path))); cl_git_pass(p_unlink(git_buf_cstr(&_path)));
cl_assert_equal_i(GIT_ENOTFOUND, git_repository_message(NULL, 0, _repo)); cl_assert_equal_i(GIT_ENOTFOUND, git_repository_message(&_actual, _repo));
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment