Skip to content

Commit

Permalink
repo: introduce git_repository_workdir_path
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
ethomson committed Apr 28, 2021
1 parent dbc03de commit 50e0121
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 0 deletions.
16 changes: 16 additions & 0 deletions src/repository.c
Original file line number Diff line number Diff line change
Expand Up @@ -2494,6 +2494,22 @@ const char *git_repository_workdir(const git_repository *repo)
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)
{
GIT_ASSERT_ARG_WITH_RETVAL(repo, NULL);
Expand Down
8 changes: 8 additions & 0 deletions src/repository.h
Original file line number Diff line number Diff line change
Expand Up @@ -241,4 +241,12 @@ bool git_repository__reserved_names(
*/
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
16 changes: 16 additions & 0 deletions tests/win32/longpath.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "clone.h"
#include "buffer.h"
#include "futils.h"
#include "repository.h"

static git_buf path = GIT_BUF_INIT;

Expand All @@ -29,6 +30,7 @@ void test_win32_longpath__initialize(void)
void test_win32_longpath__cleanup(void)
{
git_buf_dispose(&path);
cl_git_sandbox_cleanup();
}

#ifdef GIT_WIN32
Expand Down Expand Up @@ -60,3 +62,17 @@ void test_win32_longpath__errmsg_on_checkout(void)
assert_name_too_long();
#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
}

0 comments on commit 50e0121

Please sign in to comment.