Commit 50e01216 by Edward Thomson

repo: introduce git_repository_workdir_path

Add a simple accessor for workdir paths to get an absolute on-disk path
given a repository and a relative path within it.  This is useful to
avoid copy-pasta `git_buf_joinpath` and to ensure that we validate
working directory paths while honoring `core.longpaths` settings.
parent dbc03de4
...@@ -2494,6 +2494,22 @@ const char *git_repository_workdir(const git_repository *repo) ...@@ -2494,6 +2494,22 @@ const char *git_repository_workdir(const git_repository *repo)
return repo->workdir; return repo->workdir;
} }
int git_repository_workdir_path(
git_buf *out, git_repository *repo, const char *path)
{
int error;
if (!repo->workdir) {
git_error_set(GIT_ERROR_REPOSITORY, "repository has no working directory");
return GIT_EBAREREPO;
}
if (!(error = git_buf_joinpath(out, repo->workdir, path)))
error = git_path_validate_workdir_buf(repo, out);
return error;
}
const char *git_repository_commondir(const git_repository *repo) const char *git_repository_commondir(const git_repository *repo)
{ {
GIT_ASSERT_ARG_WITH_RETVAL(repo, NULL); GIT_ASSERT_ARG_WITH_RETVAL(repo, NULL);
......
...@@ -241,4 +241,12 @@ bool git_repository__reserved_names( ...@@ -241,4 +241,12 @@ bool git_repository__reserved_names(
*/ */
int git_repository_initialbranch(git_buf *out, git_repository *repo); int git_repository_initialbranch(git_buf *out, git_repository *repo);
/*
* Given a relative `path`, this makes it absolute based on the
* repository's working directory. This will perform validation
* to ensure that the path is not longer than MAX_PATH on Windows
* (unless `core.longpaths` is set in the repo config).
*/
int git_repository_workdir_path(git_buf *out, git_repository *repo, const char *path);
#endif #endif
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "clone.h" #include "clone.h"
#include "buffer.h" #include "buffer.h"
#include "futils.h" #include "futils.h"
#include "repository.h"
static git_buf path = GIT_BUF_INIT; static git_buf path = GIT_BUF_INIT;
...@@ -29,6 +30,7 @@ void test_win32_longpath__initialize(void) ...@@ -29,6 +30,7 @@ void test_win32_longpath__initialize(void)
void test_win32_longpath__cleanup(void) void test_win32_longpath__cleanup(void)
{ {
git_buf_dispose(&path); git_buf_dispose(&path);
cl_git_sandbox_cleanup();
} }
#ifdef GIT_WIN32 #ifdef GIT_WIN32
...@@ -60,3 +62,17 @@ void test_win32_longpath__errmsg_on_checkout(void) ...@@ -60,3 +62,17 @@ void test_win32_longpath__errmsg_on_checkout(void)
assert_name_too_long(); assert_name_too_long();
#endif #endif
} }
void test_win32_longpath__workdir_path_validated(void)
{
#ifdef GIT_WIN32
git_repository *repo = cl_git_sandbox_init("testrepo");
git_buf out = GIT_BUF_INIT;
cl_git_pass(git_repository_workdir_path(&out, repo, "a.txt"));
/* even if the repo path is a drive letter, this is too long */
cl_git_fail(git_repository_workdir_path(&out, repo, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.txt"));
cl_assert(git__prefixcmp(git_error_last()->message, "path too long") == 0);
#endif
}
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