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

From:
Tracey Emery <tracey@traceyemery.net>
Subject:
Re: fix 'got update' with added + obstructed file
To:
Stefan Sperling <stsp@stsp.name>
Cc:
gameoftrees@openbsd.org
Date:
Fri, 24 Sep 2021 15:44:17 -0600

Download raw body.

Thread
On Fri, Sep 24, 2021 at 11:31:14PM +0200, Stefan Sperling wrote:
> When 'got update' tries to add a new file to the work tree and this
> file is obstructed by a directory on disk, the update fails like this:
> 
>   $ got update
>   ?  new
>   got: new: Is a directory
>   $
> 
> And the work tree is not updated. The above update with error can be
> run over and over and won't proceed until the directory is removed.
> The problem here is simply that the update as a whole should succeed,
> not stop on one such file even though there might be more files to update.
> 
> With the patch below this situation is properly detected as an obstruction
> and the update succeeds:
> 
>   $ got update
>   ~  new
>   Updated to refs/heads/master: c1f85b4938dc4c668a88f13df2b98a520fc077cc
>   File paths obstructed by a non-regular file: 1
>   $
> 
> Regardless, the file 'new' will not be added to the work tree until the
> directory is moved and 'got update' is run again.
> 
> And I am extending a corresponding test to cover this issue.
> 
> ok?

Looks good.

> 
> diff f365d76274ee1ae2b57225686a0733176fc4bfb2 /home/stsp/src/got
> blob - f5bc677438d23ddca778382674edef04e09cb939
> file + lib/worktree.c
> --- lib/worktree.c
> +++ lib/worktree.c
> @@ -1942,8 +1942,20 @@ update_blob(struct got_worktree *worktree,
>  		if (status == GOT_STATUS_MISSING || status == GOT_STATUS_DELETE)
>  			sb.st_mode = got_fileindex_perms_to_st(ie);
>  	} else {
> -		sb.st_mode = GOT_DEFAULT_FILE_MODE;
> -		status = GOT_STATUS_UNVERSIONED;
> +		if (stat(ondisk_path, &sb) == -1) {
> +			if (errno != ENOENT) {
> +				err = got_error_from_errno2("stat",
> +				    ondisk_path);
> +				goto done;
> +			}
> +			sb.st_mode = GOT_DEFAULT_FILE_MODE;
> +			status = GOT_STATUS_UNVERSIONED;
> +		} else {
> +			if (S_ISREG(sb.st_mode) || S_ISLNK(sb.st_mode))
> +				status = GOT_STATUS_UNVERSIONED;
> +			else
> +				status = GOT_STATUS_OBSTRUCTED;
> +		}
>  	}
>  
>  	if (status == GOT_STATUS_OBSTRUCTED) {
> blob - cae602420f097ed69b049e9fffb3fc46510d2de5
> file + regress/cmdline/update.sh
> --- regress/cmdline/update.sh
> +++ regress/cmdline/update.sh
> @@ -2588,6 +2588,8 @@ test_update_file_skipped_due_to_obstruction() {
>  	blob_id0=`get_blob_id $testroot/repo "" beta`
>  
>  	echo "changed beta" > $testroot/repo/beta
> +	echo "new file" > $testroot/repo/new
> +	(cd $testroot/repo && git add new)
>  	git_commit $testroot/repo -m "changed beta"
>  	local commit_id1=`git_show_head $testroot/repo`
>  	blob_id1=`get_blob_id $testroot/repo "" beta`
> @@ -2617,14 +2619,22 @@ test_update_file_skipped_due_to_obstruction() {
>  
>  	rm $testroot/wt/beta
>  	mkdir -p $testroot/wt/beta/psi
> +	mkdir -p $testroot/wt/new
>  
> -	# update to the latest commit; this skips beta
> +	# update to the latest commit; this skips beta and the new file
>  	(cd $testroot/wt && got update > $testroot/stdout)
> +	ret="$?"
> +	if [ "$ret" != "0" ]; then
> +		echo "update failed unexpectedly" >&2
> +		test_done "$testroot" "1"
> +		return 1
> +	fi
>  
>  	echo "~  beta" > $testroot/stdout.expected
> +	echo "~  new" >> $testroot/stdout.expected
>  	echo "Updated to refs/heads/master: $commit_id1" \
>  		>> $testroot/stdout.expected
> -	echo "File paths obstructed by a non-regular file: 1" \
> +	echo "File paths obstructed by a non-regular file: 2" \
>  		>> $testroot/stdout.expected
>  	cmp -s $testroot/stdout.expected $testroot/stdout
>  	ret="$?"
> @@ -2656,8 +2666,11 @@ test_update_file_skipped_due_to_obstruction() {
>  	# updating to the latest commit should now update beta
>  	(cd $testroot/wt && got update > $testroot/stdout)
>  	echo "!  beta" > $testroot/stdout.expected
> +	echo "~  new" >> $testroot/stdout.expected
>  	echo "Updated to refs/heads/master: $commit_id1" \
>  		>> $testroot/stdout.expected
> +	echo "File paths obstructed by a non-regular file: 1" \
> +		>> $testroot/stdout.expected
>  	cmp -s $testroot/stdout.expected $testroot/stdout
>  	ret="$?"
>  	if [ "$ret" != "0" ]; then

-- 

Tracey Emery