Skip to content

Commit cf958b9

Browse files
derrickstoleedscho
authored andcommitted
setup: add discover_git_directory_reason()
There are many reasons why discovering a Git directory may fail. In particular, 8959555 (setup_git_directory(): add an owner check for the top-level directory, 2022-03-02) added ownership checks as a security precaution. Callers attempting to set up a Git directory may want to inform the user about the reason for the failure. For that, expose the enum discovery_result from within setup.c and into cache.h where discover_git_directory() is defined. I initially wanted to change the return type of discover_git_directory() to be this enum, but several callers rely upon the "zero means success". The two problems with this are: 1. The zero value of the enum is actually GIT_DIR_NONE, so nonpositive results are errors. 2. There are multiple successful states, so some positive results are successful. Instead of updating all callers immediately, add a new method, discover_git_directory_reason(), and convert discover_git_directory() to be a thin shim on top of it. Because there are extra checks that discover_git_directory_reason() does after setup_git_directory_gently_1(), there are other modes that can be returned for failure states. Add these modes to the enum, but be sure to explicitly add them as BUG() states in the switch of setup_git_directory_gently(). Signed-off-by: Derrick Stolee <derrickstolee@github.com>
1 parent cd1cd80 commit cf958b9

2 files changed

Lines changed: 41 additions & 23 deletions

File tree

setup.c

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1221,19 +1221,6 @@ static const char *allowed_bare_repo_to_string(
12211221
return NULL;
12221222
}
12231223

1224-
enum discovery_result {
1225-
GIT_DIR_NONE = 0,
1226-
GIT_DIR_EXPLICIT,
1227-
GIT_DIR_DISCOVERED,
1228-
GIT_DIR_BARE,
1229-
/* these are errors */
1230-
GIT_DIR_HIT_CEILING = -1,
1231-
GIT_DIR_HIT_MOUNT_POINT = -2,
1232-
GIT_DIR_INVALID_GITFILE = -3,
1233-
GIT_DIR_INVALID_OWNERSHIP = -4,
1234-
GIT_DIR_DISALLOWED_BARE = -5,
1235-
};
1236-
12371224
/*
12381225
* We cannot decide in this function whether we are in the work tree or
12391226
* not, since the config can only be read _after_ this function was called.
@@ -1385,21 +1372,22 @@ static enum discovery_result setup_git_directory_gently_1(struct strbuf *dir,
13851372
}
13861373
}
13871374

1388-
int discover_git_directory(struct strbuf *commondir,
1389-
struct strbuf *gitdir)
1375+
enum discovery_result discover_git_directory_reason(struct strbuf *commondir,
1376+
struct strbuf *gitdir)
13901377
{
13911378
struct strbuf dir = STRBUF_INIT, err = STRBUF_INIT;
13921379
size_t gitdir_offset = gitdir->len, cwd_len;
13931380
size_t commondir_offset = commondir->len;
13941381
struct repository_format candidate = REPOSITORY_FORMAT_INIT;
1382+
enum discovery_result result;
13951383

13961384
if (strbuf_getcwd(&dir))
1397-
return -1;
1385+
return GIT_DIR_CWD_FAILURE;
13981386

13991387
cwd_len = dir.len;
1400-
if (setup_git_directory_gently_1(&dir, gitdir, NULL, 0) <= 0) {
1388+
if ((result = setup_git_directory_gently_1(&dir, gitdir, NULL, 0)) <= 0) {
14011389
strbuf_release(&dir);
1402-
return -1;
1390+
return result;
14031391
}
14041392

14051393
/*
@@ -1429,11 +1417,11 @@ int discover_git_directory(struct strbuf *commondir,
14291417
strbuf_setlen(commondir, commondir_offset);
14301418
strbuf_setlen(gitdir, gitdir_offset);
14311419
clear_repository_format(&candidate);
1432-
return -1;
1420+
return GIT_DIR_INVALID_FORMAT;
14331421
}
14341422

14351423
clear_repository_format(&candidate);
1436-
return 0;
1424+
return result;
14371425
}
14381426

14391427
const char *setup_git_directory_gently(int *nongit_ok)
@@ -1525,9 +1513,11 @@ const char *setup_git_directory_gently(int *nongit_ok)
15251513
*nongit_ok = 1;
15261514
break;
15271515
case GIT_DIR_NONE:
1516+
case GIT_DIR_CWD_FAILURE:
1517+
case GIT_DIR_INVALID_FORMAT:
15281518
/*
15291519
* As a safeguard against setup_git_directory_gently_1 returning
1530-
* this value, fallthrough to BUG. Otherwise it is possible to
1520+
* these values, fallthrough to BUG. Otherwise it is possible to
15311521
* set startup_info->have_repository to 1 when we did nothing to
15321522
* find a repository.
15331523
*/

setup.h

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,30 @@ const char *resolve_gitdir_gently(const char *suspect, int *return_error_code);
4242
#define resolve_gitdir(path) resolve_gitdir_gently((path), NULL)
4343

4444
void setup_work_tree(void);
45+
46+
/*
47+
* discover_git_directory_reason() is similar to discover_git_directory(),
48+
* except it returns an enum value instead. It is important to note that
49+
* a zero-valued return here is actually GIT_DIR_NONE, which is different
50+
* from discover_git_directory.
51+
*/
52+
enum discovery_result {
53+
GIT_DIR_NONE = 0,
54+
GIT_DIR_EXPLICIT,
55+
GIT_DIR_DISCOVERED,
56+
GIT_DIR_BARE,
57+
/* these are errors */
58+
GIT_DIR_HIT_CEILING = -1,
59+
GIT_DIR_HIT_MOUNT_POINT = -2,
60+
GIT_DIR_INVALID_GITFILE = -3,
61+
GIT_DIR_INVALID_OWNERSHIP = -4,
62+
GIT_DIR_DISALLOWED_BARE = -5,
63+
GIT_DIR_INVALID_FORMAT = -6,
64+
GIT_DIR_CWD_FAILURE = -7,
65+
};
66+
enum discovery_result discover_git_directory_reason(struct strbuf *commondir,
67+
struct strbuf *gitdir);
68+
4569
/*
4670
* Find the commondir and gitdir of the repository that contains the current
4771
* working directory, without changing the working directory or other global
@@ -50,8 +74,12 @@ void setup_work_tree(void);
5074
* both have the same result appended to the buffer. The return value is
5175
* either 0 upon success and non-zero if no repository was found.
5276
*/
53-
int discover_git_directory(struct strbuf *commondir,
54-
struct strbuf *gitdir);
77+
static inline int discover_git_directory(struct strbuf *commondir,
78+
struct strbuf *gitdir)
79+
{
80+
return discover_git_directory_reason(commondir, gitdir) <= 0;
81+
}
82+
5583
const char *setup_git_directory_gently(int *);
5684
const char *setup_git_directory(void);
5785
char *prefix_path(const char *prefix, int len, const char *path);

0 commit comments

Comments
 (0)