Skip to content

Commit cb3269c

Browse files
committed
repository: add function to retrieve paths for repo items
1 parent c09fd54 commit cb3269c

File tree

2 files changed

+97
-0
lines changed

2 files changed

+97
-0
lines changed

include/git2/repository.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,42 @@ GIT_EXTERN(int) git_repository_head_unborn(git_repository *repo);
370370
*/
371371
GIT_EXTERN(int) git_repository_is_empty(git_repository *repo);
372372

373+
/**
374+
* List of items which belong to the git repository layout
375+
*/
376+
typedef enum {
377+
GIT_REPOSITORY_ITEM_GITDIR,
378+
GIT_REPOSITORY_ITEM_WORKDIR,
379+
GIT_REPOSITORY_ITEM_COMMONDIR,
380+
GIT_REPOSITORY_ITEM_INDEX,
381+
GIT_REPOSITORY_ITEM_OBJECTS,
382+
GIT_REPOSITORY_ITEM_REFS,
383+
GIT_REPOSITORY_ITEM_PACKED_REFS,
384+
GIT_REPOSITORY_ITEM_REMOTES,
385+
GIT_REPOSITORY_ITEM_CONFIG,
386+
GIT_REPOSITORY_ITEM_INFO,
387+
GIT_REPOSITORY_ITEM_HOOKS,
388+
GIT_REPOSITORY_ITEM_LOGS,
389+
GIT_REPOSITORY_ITEM_MODULES,
390+
GIT_REPOSITORY_ITEM_WORKTREES
391+
} git_repository_item_t;
392+
393+
/**
394+
* Get the location of a specific repository file or directory
395+
*
396+
* This function will retrieve the path of a specific repository
397+
* item. It will thereby honor things like the repository's
398+
* common directory, gitdir, etc. In case a file path cannot
399+
* exist for a given item (e.g. the working directory of a bare
400+
* repository), an error is returned.
401+
*
402+
* @param out Buffer to store the path at
403+
* @param repo Repository to get path for
404+
* @param item The repository item for which to retrieve the path
405+
* @return 0 on success, otherwise a negative value
406+
*/
407+
GIT_EXTERN(int) git_repository_item_path(git_buf *out, git_repository *repo, git_repository_item_t item);
408+
373409
/**
374410
* Get the path of this repository
375411
*

src/repository.c

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,27 @@ GIT__USE_STRMAP
3636
# include "win32/w32_util.h"
3737
#endif
3838

39+
static const struct {
40+
git_repository_item_t parent;
41+
const char *name;
42+
bool directory;
43+
} items[] = {
44+
{ GIT_REPOSITORY_ITEM_GITDIR, NULL, true },
45+
{ GIT_REPOSITORY_ITEM_WORKDIR, NULL, true },
46+
{ GIT_REPOSITORY_ITEM_COMMONDIR, NULL, true },
47+
{ GIT_REPOSITORY_ITEM_GITDIR, "index", false },
48+
{ GIT_REPOSITORY_ITEM_COMMONDIR, "objects", true },
49+
{ GIT_REPOSITORY_ITEM_COMMONDIR, "refs", true },
50+
{ GIT_REPOSITORY_ITEM_COMMONDIR, "packed-refs", false },
51+
{ GIT_REPOSITORY_ITEM_COMMONDIR, "remotes", true },
52+
{ GIT_REPOSITORY_ITEM_COMMONDIR, "config", false },
53+
{ GIT_REPOSITORY_ITEM_COMMONDIR, "info", true },
54+
{ GIT_REPOSITORY_ITEM_COMMONDIR, "hooks", true },
55+
{ GIT_REPOSITORY_ITEM_COMMONDIR, "logs", true },
56+
{ GIT_REPOSITORY_ITEM_GITDIR, "modules", true },
57+
{ GIT_REPOSITORY_ITEM_COMMONDIR, "worktrees", true }
58+
};
59+
3960
static int check_repositoryformatversion(git_config *config);
4061

4162
#define GIT_COMMONDIR_FILE "commondir"
@@ -2052,6 +2073,46 @@ int git_repository_is_empty(git_repository *repo)
20522073
return is_empty;
20532074
}
20542075

2076+
int git_repository_item_path(git_buf *out, git_repository *repo, git_repository_item_t item)
2077+
{
2078+
const char *parent;
2079+
2080+
switch (items[item].parent) {
2081+
case GIT_REPOSITORY_ITEM_GITDIR:
2082+
parent = git_repository_path(repo);
2083+
break;
2084+
case GIT_REPOSITORY_ITEM_WORKDIR:
2085+
parent = git_repository_workdir(repo);
2086+
break;
2087+
case GIT_REPOSITORY_ITEM_COMMONDIR:
2088+
parent = git_repository_commondir(repo);
2089+
break;
2090+
default:
2091+
giterr_set(GITERR_INVALID, "Invalid item directory");
2092+
return -1;
2093+
}
2094+
2095+
if (parent == NULL) {
2096+
giterr_set(GITERR_INVALID, "Path cannot exist in repository");
2097+
return -1;
2098+
}
2099+
2100+
if (git_buf_sets(out, parent) < 0)
2101+
return -1;
2102+
2103+
if (items[item].name) {
2104+
if (git_buf_joinpath(out, parent, items[item].name) < 0)
2105+
return -1;
2106+
}
2107+
2108+
if (items[item].directory) {
2109+
if (git_path_to_dir(out) < 0)
2110+
return -1;
2111+
}
2112+
2113+
return 0;
2114+
}
2115+
20552116
const char *git_repository_path(git_repository *repo)
20562117
{
20572118
assert(repo);

0 commit comments

Comments
 (0)