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`.
parent 9f723c97
...@@ -438,7 +438,8 @@ typedef enum { ...@@ -438,7 +438,8 @@ typedef enum {
GIT_REPOSITORY_ITEM_HOOKS, GIT_REPOSITORY_ITEM_HOOKS,
GIT_REPOSITORY_ITEM_LOGS, GIT_REPOSITORY_ITEM_LOGS,
GIT_REPOSITORY_ITEM_MODULES, GIT_REPOSITORY_ITEM_MODULES,
GIT_REPOSITORY_ITEM_WORKTREES GIT_REPOSITORY_ITEM_WORKTREES,
GIT_REPOSITORY_ITEM__LAST
} git_repository_item_t; } git_repository_item_t;
/** /**
......
...@@ -25,6 +25,10 @@ GIT_BEGIN_DECL ...@@ -25,6 +25,10 @@ GIT_BEGIN_DECL
* Note that this is only useful if you wish to associate the repository * Note that this is only useful if you wish to associate the repository
* with a non-filesystem-backed object database and config store. * with a non-filesystem-backed object database and config store.
* *
* Caveats: since this repository has no physical location, some systems
* can fail to function properly: locations under $GIT_DIR, $GIT_COMMON_DIR,
* or $GIT_INFO_DIR are impacted.
*
* @param out The blank repository * @param out The blank repository
* @return 0 on success, or an error code * @return 0 on success, or an error code
*/ */
......
...@@ -42,23 +42,24 @@ bool git_repository__fsync_gitdir = false; ...@@ -42,23 +42,24 @@ bool git_repository__fsync_gitdir = false;
static const struct { static const struct {
git_repository_item_t parent; git_repository_item_t parent;
git_repository_item_t fallback;
const char *name; const char *name;
bool directory; bool directory;
} items[] = { } items[] = {
{ GIT_REPOSITORY_ITEM_GITDIR, NULL, true }, { GIT_REPOSITORY_ITEM_GITDIR, GIT_REPOSITORY_ITEM__LAST, NULL, true },
{ GIT_REPOSITORY_ITEM_WORKDIR, NULL, true }, { GIT_REPOSITORY_ITEM_WORKDIR, GIT_REPOSITORY_ITEM__LAST, NULL, true },
{ GIT_REPOSITORY_ITEM_COMMONDIR, NULL, true }, { GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM__LAST, NULL, true },
{ GIT_REPOSITORY_ITEM_GITDIR, "index", false }, { GIT_REPOSITORY_ITEM_GITDIR, GIT_REPOSITORY_ITEM__LAST, "index", false },
{ GIT_REPOSITORY_ITEM_COMMONDIR, "objects", true }, { GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "objects", true },
{ GIT_REPOSITORY_ITEM_COMMONDIR, "refs", true }, { GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "refs", true },
{ GIT_REPOSITORY_ITEM_COMMONDIR, "packed-refs", false }, { GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "packed-refs", false },
{ GIT_REPOSITORY_ITEM_COMMONDIR, "remotes", true }, { GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "remotes", true },
{ GIT_REPOSITORY_ITEM_COMMONDIR, "config", false }, { GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "config", false },
{ GIT_REPOSITORY_ITEM_COMMONDIR, "info", true }, { GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "info", true },
{ GIT_REPOSITORY_ITEM_COMMONDIR, "hooks", true }, { GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "hooks", true },
{ GIT_REPOSITORY_ITEM_COMMONDIR, "logs", true }, { GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "logs", true },
{ GIT_REPOSITORY_ITEM_GITDIR, "modules", true }, { GIT_REPOSITORY_ITEM_GITDIR, GIT_REPOSITORY_ITEM__LAST, "modules", true },
{ GIT_REPOSITORY_ITEM_COMMONDIR, "worktrees", true } { GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "worktrees", true }
}; };
static int check_repositoryformatversion(git_config *config); static int check_repositoryformatversion(git_config *config);
...@@ -2308,11 +2309,11 @@ int git_repository_is_empty(git_repository *repo) ...@@ -2308,11 +2309,11 @@ int git_repository_is_empty(git_repository *repo)
return is_empty; return is_empty;
} }
int git_repository_item_path(git_buf *out, const git_repository *repo, git_repository_item_t item) static const char *resolved_parent_path(const git_repository *repo, git_repository_item_t item, git_repository_item_t fallback)
{ {
const char *parent; const char *parent;
switch (items[item].parent) { switch (item) {
case GIT_REPOSITORY_ITEM_GITDIR: case GIT_REPOSITORY_ITEM_GITDIR:
parent = git_repository_path(repo); parent = git_repository_path(repo);
break; break;
...@@ -2324,9 +2325,17 @@ int git_repository_item_path(git_buf *out, const git_repository *repo, git_repos ...@@ -2324,9 +2325,17 @@ int git_repository_item_path(git_buf *out, const git_repository *repo, git_repos
break; break;
default: default:
git_error_set(GIT_ERROR_INVALID, "invalid item directory"); git_error_set(GIT_ERROR_INVALID, "invalid item directory");
return -1; return NULL;
} }
if (!parent && fallback != GIT_REPOSITORY_ITEM__LAST)
return resolved_parent_path(repo, fallback, GIT_REPOSITORY_ITEM__LAST);
return parent;
}
int git_repository_item_path(git_buf *out, const git_repository *repo, git_repository_item_t item)
{
const char *parent = resolved_parent_path(repo, items[item].parent, items[item].fallback);
if (parent == NULL) { if (parent == NULL) {
git_error_set(GIT_ERROR_INVALID, "path cannot exist in repository"); git_error_set(GIT_ERROR_INVALID, "path cannot exist in repository");
return GIT_ENOTFOUND; return GIT_ENOTFOUND;
......
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