Erik Elfström <erik.elfst...@gmail.com> 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 <gits...@pobox.com>
> Helped-by: Jeff King <p...@peff.net>
> Signed-off-by: Erik Elfström <erik.elfst...@gmail.com>
> ---
>  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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to