"GOT", but the "O" is a cute, smiling pufferfish. Index | Thread | Search

From:
Ted Bullock <tbullock@comlore.com>
Subject:
Re: Workflow question, maybe bug or unclear usage.
To:
Christian Weisgerber <naddy@mips.inka.de>, gameoftrees@openbsd.org
Date:
Tue, 25 Jan 2022 17:09:14 -0700

Download raw body.

Thread
On 2022-01-25 3:47 p.m., Stefan Sperling wrote:
> On Tue, Jan 25, 2022 at 11:27:59PM +0100, Christian Weisgerber wrote:
>> Christian Weisgerber:
>>
>>>> For me, using `got checkout` on an NFS share, causes `got status` to
>>>> report all directories in the work tree with the bogus *?* status as below:
>>>
>>> FWIW, I can reproduce this.
>>
>> A guess would be that status_new() needs to call got_path_dirent_type()
>> and not rely on dirent->d_type, which is DT_UNKNOWN for all entries
>> on NFS.
>>
> 
> Yes, I missed applying the DT_UKNOWN workaround in this case.
> 
> This patch fixes the issue. ok?

Works for me.

> 
> diff 4362cf9c24c2ad037cda602ae688bef54869f793 /home/stsp/src/got
> blob - 71a058b11b7499d2dd17a72a9d69aafdb49f8874
> file + lib/fileindex.c
> --- lib/fileindex.c
> +++ lib/fileindex.c
> @@ -1022,28 +1022,15 @@ walk_dir(struct got_pathlist_entry **next, struct got_
>   	struct dirent *de = dle->data;
>   	DIR *subdir = NULL;
>   	int subdirfd = -1;
> -	int type;
>   
>   	*next = NULL;
>   
> -	if (de->d_type == DT_UNKNOWN) {
> -		/* Occurs on NFS mounts without "readdir plus" RPC. */
> -		char *dir_path;
> -		if (asprintf(&dir_path, "%s/%s", rootpath, path) == -1)
> -			return got_error_from_errno("asprintf");
> -		err = got_path_dirent_type(&type, dir_path, de);
> -		free(dir_path);
> -		if (err)
> -			return err;
> -	} else
> -		type = de->d_type;
> -
>   	/* Must traverse ignored directories if they contain tracked files. */
> -	if (type == DT_DIR && ignore &&
> +	if (de->d_type == DT_DIR && ignore &&
>   	    have_tracked_file_in_dir(fileindex, path))
>   		ignore = 0;
>   
> -	if (type == DT_DIR && !ignore) {
> +	if (de->d_type == DT_DIR && !ignore) {
>   		char *subpath;
>   		char *subdirpath;
>   		struct got_pathlist_head subdirlist;
> @@ -1099,6 +1086,28 @@ walk_dir(struct got_pathlist_entry **next, struct got_
>   }
>   
>   static const struct got_error *
> +dirent_type_fixup(struct dirent *de, const char *rootpath, const char *path)
> +{
> +	const struct got_error *err;
> +	char *dir_path;
> +	int type;
> +
> +	if (de->d_type != DT_UNKNOWN)
> +		return NULL;
> +
> +	/* DT_UNKNOWN occurs on NFS mounts without "readdir plus" RPC. */
> +	if (asprintf(&dir_path, "%s/%s", rootpath, path) == -1)
> +		return got_error_from_errno("asprintf");
> +	err = got_path_dirent_type(&type, dir_path, de);
> +	free(dir_path);
> +	if (err)
> +		return err;
> +
> +	de->d_type = type;
> +	return NULL;
> +}
> +
> +static const struct got_error *
>   diff_fileindex_dir(struct got_fileindex *fileindex,
>       struct got_fileindex_entry **ie, struct got_pathlist_head *dirlist,
>       int dirfd, const char *rootpath, const char *path,
> @@ -1123,6 +1132,9 @@ diff_fileindex_dir(struct got_fileindex *fileindex,
>   			char *de_path;
>   			int cmp;
>   			de = dle->data;
> +			err = dirent_type_fixup(de, rootpath, path);
> +			if (err)
> +				break;
>   			if (asprintf(&de_path, "%s/%s", path,
>   			    de->d_name) == -1) {
>   				err = got_error_from_errno("asprintf");
> @@ -1162,6 +1174,9 @@ diff_fileindex_dir(struct got_fileindex *fileindex,
>   			*ie = walk_fileindex(fileindex, *ie);
>   		} else if (dle) {
>   			de = dle->data;
> +			err = dirent_type_fixup(de, rootpath, path);
> +			if (err)
> +				break;
>   			err = cb->diff_new(&ignore, cb_arg, de, path, dirfd);
>   			if (err)
>   				break;

-- 
Ted Bullock <tbullock@comlore.com>