Re: [PATCH v4 1/5] setup: add gentle version of read_gitfile

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Erik Elfström <erik.elfstrom@xxxxxxxxx> 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 <gitster@xxxxxxxxx>
> Helped-by: Jeff King <peff@xxxxxxxx>
> Signed-off-by: Erik Elfström <erik.elfstrom@xxxxxxxxx>
> ---
>  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 majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]