Skip to content

Commit 501c51b

Browse files
committed
repo: commondir resolution can sometimes fallback to the repodir
For example, https://git-scm.com/docs/gitrepository-layout says: info Additional information about the repository is recorded in this directory. This directory is ignored if $GIT_COMMON_DIR is set and "$GIT_COMMON_DIR/info" will be used instead. So when looking for `info/attributes`, we need to check the commondir first, or fallback to "our" `info/attributes`.
1 parent 9f723c9 commit 501c51b

File tree

3 files changed

+32
-18
lines changed

3 files changed

+32
-18
lines changed

include/git2/repository.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,8 @@ typedef enum {
438438
GIT_REPOSITORY_ITEM_HOOKS,
439439
GIT_REPOSITORY_ITEM_LOGS,
440440
GIT_REPOSITORY_ITEM_MODULES,
441-
GIT_REPOSITORY_ITEM_WORKTREES
441+
GIT_REPOSITORY_ITEM_WORKTREES,
442+
GIT_REPOSITORY_ITEM__LAST
442443
} git_repository_item_t;
443444

444445
/**

include/git2/sys/repository.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ GIT_BEGIN_DECL
2525
* Note that this is only useful if you wish to associate the repository
2626
* with a non-filesystem-backed object database and config store.
2727
*
28+
* Caveats: since this repository has no physical location, some systems
29+
* can fail to function properly: locations under $GIT_DIR, $GIT_COMMON_DIR,
30+
* or $GIT_INFO_DIR are impacted.
31+
*
2832
* @param out The blank repository
2933
* @return 0 on success, or an error code
3034
*/

src/repository.c

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -42,23 +42,24 @@ bool git_repository__fsync_gitdir = false;
4242

4343
static const struct {
4444
git_repository_item_t parent;
45+
git_repository_item_t fallback;
4546
const char *name;
4647
bool directory;
4748
} items[] = {
48-
{ GIT_REPOSITORY_ITEM_GITDIR, NULL, true },
49-
{ GIT_REPOSITORY_ITEM_WORKDIR, NULL, true },
50-
{ GIT_REPOSITORY_ITEM_COMMONDIR, NULL, true },
51-
{ GIT_REPOSITORY_ITEM_GITDIR, "index", false },
52-
{ GIT_REPOSITORY_ITEM_COMMONDIR, "objects", true },
53-
{ GIT_REPOSITORY_ITEM_COMMONDIR, "refs", true },
54-
{ GIT_REPOSITORY_ITEM_COMMONDIR, "packed-refs", false },
55-
{ GIT_REPOSITORY_ITEM_COMMONDIR, "remotes", true },
56-
{ GIT_REPOSITORY_ITEM_COMMONDIR, "config", false },
57-
{ GIT_REPOSITORY_ITEM_COMMONDIR, "info", true },
58-
{ GIT_REPOSITORY_ITEM_COMMONDIR, "hooks", true },
59-
{ GIT_REPOSITORY_ITEM_COMMONDIR, "logs", true },
60-
{ GIT_REPOSITORY_ITEM_GITDIR, "modules", true },
61-
{ GIT_REPOSITORY_ITEM_COMMONDIR, "worktrees", true }
49+
{ GIT_REPOSITORY_ITEM_GITDIR, GIT_REPOSITORY_ITEM__LAST, NULL, true },
50+
{ GIT_REPOSITORY_ITEM_WORKDIR, GIT_REPOSITORY_ITEM__LAST, NULL, true },
51+
{ GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM__LAST, NULL, true },
52+
{ GIT_REPOSITORY_ITEM_GITDIR, GIT_REPOSITORY_ITEM__LAST, "index", false },
53+
{ GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "objects", true },
54+
{ GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "refs", true },
55+
{ GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "packed-refs", false },
56+
{ GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "remotes", true },
57+
{ GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "config", false },
58+
{ GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "info", true },
59+
{ GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "hooks", true },
60+
{ GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "logs", true },
61+
{ GIT_REPOSITORY_ITEM_GITDIR, GIT_REPOSITORY_ITEM__LAST, "modules", true },
62+
{ GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "worktrees", true }
6263
};
6364

6465
static int check_repositoryformatversion(git_config *config);
@@ -2308,11 +2309,11 @@ int git_repository_is_empty(git_repository *repo)
23082309
return is_empty;
23092310
}
23102311

2311-
int git_repository_item_path(git_buf *out, const git_repository *repo, git_repository_item_t item)
2312+
static const char *resolved_parent_path(const git_repository *repo, git_repository_item_t item, git_repository_item_t fallback)
23122313
{
23132314
const char *parent;
23142315

2315-
switch (items[item].parent) {
2316+
switch (item) {
23162317
case GIT_REPOSITORY_ITEM_GITDIR:
23172318
parent = git_repository_path(repo);
23182319
break;
@@ -2324,9 +2325,17 @@ int git_repository_item_path(git_buf *out, const git_repository *repo, git_repos
23242325
break;
23252326
default:
23262327
git_error_set(GIT_ERROR_INVALID, "invalid item directory");
2327-
return -1;
2328+
return NULL;
23282329
}
2330+
if (!parent && fallback != GIT_REPOSITORY_ITEM__LAST)
2331+
return resolved_parent_path(repo, fallback, GIT_REPOSITORY_ITEM__LAST);
2332+
2333+
return parent;
2334+
}
23292335

2336+
int git_repository_item_path(git_buf *out, const git_repository *repo, git_repository_item_t item)
2337+
{
2338+
const char *parent = resolved_parent_path(repo, items[item].parent, items[item].fallback);
23302339
if (parent == NULL) {
23312340
git_error_set(GIT_ERROR_INVALID, "path cannot exist in repository");
23322341
return GIT_ENOTFOUND;

0 commit comments

Comments
 (0)