Erik Elfström <[email protected]> writes:
> read_gitfile will die on most error cases. This makes it unsuitable
> for speculative calls. Extract the core logic and provide a gentle
> version that returns NULL on failure.
>
> The first usecase of the new gentle version will be to probe for
> submodules during git clean.
>
> Helped-by: Junio C Hamano <[email protected]>
> Helped-by: Jeff King <[email protected]>
> Signed-off-by: Erik Elfström <[email protected]>
> ---
> cache.h | 3 ++-
> setup.c | 82
> +++++++++++++++++++++++++++++++++++++++++++++++++++--------------
> 2 files changed, 67 insertions(+), 18 deletions(-)
>
> diff --git a/cache.h b/cache.h
> index 3d3244b..6e29068 100644
> --- a/cache.h
> +++ b/cache.h
> @@ -431,7 +431,8 @@ extern int set_git_dir(const char *path);
> extern const char *get_git_namespace(void);
> extern const char *strip_namespace(const char *namespaced_ref);
> extern const char *get_git_work_tree(void);
> -extern const char *read_gitfile(const char *path);
> +extern const char *read_gitfile_gently(const char *path, int
> *return_error_code);
> +#define read_gitfile(path) read_gitfile_gently((path), NULL)
> extern const char *resolve_gitdir(const char *suspect);
> extern void set_git_work_tree(const char *tree);
>
> diff --git a/setup.c b/setup.c
> index 979b13f..e1897cc 100644
> --- a/setup.c
> +++ b/setup.c
> @@ -335,35 +335,53 @@ static int check_repository_format_gently(const char
> *gitdir, int *nongit_ok)
> /*
> * Try to read the location of the git directory from the .git file,
> * return path to git directory if found.
> + *
> + * On failure, if return_error_code is not NULL, return_error_code
> + * will be set to an error code and NULL will be returned. If
> + * return_error_code is NULL the function will die instead (for most
> + * cases).
> */
> -const char *read_gitfile(const char *path)
> +const char *read_gitfile_gently(const char *path, int *return_error_code)
> {
> - char *buf;
> - char *dir;
> + int error_code = 0;
> + char *buf = NULL;
> + char *dir = NULL;
> const char *slash;
> struct stat st;
> int fd;
> ssize_t len;
>
> - if (stat(path, &st))
> - return NULL;
> - if (!S_ISREG(st.st_mode))
> - return NULL;
> + if (stat(path, &st)) {
> + error_code = 1;
> + goto cleanup_return;
> + }
> + if (!S_ISREG(st.st_mode)) {
> + error_code = 2;
> + goto cleanup_return;
> + }
> fd = open(path, O_RDONLY);
> - if (fd < 0)
> - die_errno("Error opening '%s'", path);
> + if (fd < 0) {
> + error_code = 3;
> + goto cleanup_return;
> + }
> buf = xmalloc(st.st_size + 1);
> len = read_in_full(fd, buf, st.st_size);
> close(fd);
> - if (len != st.st_size)
> - die("Error reading %s", path);
> + if (len != st.st_size) {
> + error_code = 4;
> + goto cleanup_return;
> + }
> buf[len] = '\0';
> - if (!starts_with(buf, "gitdir: "))
> - die("Invalid gitfile format: %s", path);
> + if (!starts_with(buf, "gitdir: ")) {
> + error_code = 5;
> + goto cleanup_return;
> + }
> while (buf[len - 1] == '\n' || buf[len - 1] == '\r')
> len--;
> - if (len < 9)
> - die("No path in gitfile: %s", path);
> + if (len < 9) {
> + error_code = 6;
> + goto cleanup_return;
> + }
> buf[len] = '\0';
> dir = buf + 8;
>
> @@ -378,11 +396,41 @@ const char *read_gitfile(const char *path)
> buf = dir;
> }
>
> - if (!is_git_directory(dir))
> - die("Not a git repository: %s", dir);
> + if (!is_git_directory(dir)) {
> + error_code = 7;
> + goto cleanup_return;
> + }
> path = real_path(dir);
>
> +cleanup_return:
> free(buf);
> +
> + if (return_error_code)
> + *return_error_code = error_code;
> +
> + if (error_code) {
> + if (return_error_code)
> + return NULL;
> +
> + switch (error_code) {
> + case 1: // failed to stat
> + case 2: // not regular file
Please do not use C++ // comments.
> + return NULL;
> + case 3:
> + die_errno("Error opening '%s'", path);
> + case 4:
> + die("Error reading %s", path);
> + case 5:
> + die("Invalid gitfile format: %s", path);
> + case 6:
> + die("No path in gitfile: %s", path);
> + case 7:
> + die("Not a git repository: %s", dir);
> + default:
> + assert(0);
> + }
> + }
> +
> return path;
> }
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html