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

From:
Omar Polo <op@omarpolo.com>
Subject:
Re: staging the reverse of the staged diff
To:
Omar Polo <op@omarpolo.com>
Cc:
gameoftrees@openbsd.org
Date:
Fri, 03 Jun 2022 11:50:21 +0200

Download raw body.

Thread
Omar Polo <op@omarpolo.com> wrote:
> found this by chance; i've staged a debug printf somewhere by accident,
> then removed, staged the removal and... the file was still staged but
> with an empty diff!  (it was the only edit to that file)
> 
> patch below tries to make stage_path slightly more clever by checking
> the staged blob and the file blob: if they're the same we've effectively
> unstaged a file.
> 
> does this makes sense?  am i trying to make 'got stage' too much clever?

forgot to mention one thing, it's explicit that 'got stage' still prints
'M' when automatically unstaging as a visual confirmation for the user
that the file was affected.

compare

	$ got stage alpha
	 M alpha
	$ got diff -s | got patch -R
	 M alpha
	$ got stage alpha
	 M alpha			# ok, i know alpha was affected
	$ got status
	$

with

	$ ...
	$ got stage alpha
	$ got status			# ??? it worked?
	$ 

> on the other hand, this 'got stage' trick can be used to make empty
> commits:
> 
> 	$ echo clobber > got/got.c
> 	$ got stage got/got.c
> 	$ got diff -s | got patch -R
> 	$ got stage got/got.c
> 	$ got commit -m "I'm an empty commit!"
> 
> but feels hackish :)
> 
> (some project sometimes requires the contributor to make an "empty
> commit" for copyright stuff, see for e.g.
> https://github.com/mawww/kakoune/blob/master/CONTRIBUTING, but this is
> probably a separate issue.)
> 
> diff ce2bf7b7c9058374563c6db8608dbab9df2bba7d /home/op/w/got
> blob - ca8e4d6a6ba63c5f3e16487196a7a3bf16fa888b
> file + lib/worktree.c
> --- lib/worktree.c
> +++ lib/worktree.c
> @@ -8068,6 +8068,17 @@ stage_path(void *arg, unsigned char status,
>  		err = (*a->status_cb)(a->status_arg, GOT_STATUS_NO_CHANGE,
>  		    get_staged_status(ie), relpath, blob_id,
>  		    new_staged_blob_id, NULL, dirfd, de_name);
> +		if (err)
> +			break;
> +		/*
> +		 * When staging the reverse of the staged diff,
> +		 * implicitly unstage the file.
> +		 */
> +		if (memcmp(ie->staged_blob_sha1, ie->blob_sha1,
> +		    sizeof(ie->blob_sha1)) == 0) {
> +			got_fileindex_entry_stage_set(ie,
> +			    GOT_FILEIDX_STAGE_NONE);
> +		}
>  		break;
>  	case GOT_STATUS_DELETE:
>  		if (staged_status == GOT_STATUS_DELETE)
> blob - e16d9854340821bff1be14c3086fbe1a59b26843
> file + regress/cmdline/stage.sh
> --- regress/cmdline/stage.sh
> +++ regress/cmdline/stage.sh
> @@ -2154,6 +2154,59 @@ test_stage_patch_removed_twice() {
>  	test_done "$testroot" "$ret"
>  }
>  
> +test_stage_patch_reversed() {
> +	local testroot=`test_init stage_patch_reversed`
> +
> +	got checkout $testroot/repo $testroot/wt > /dev/null
> +	ret=$?
> +	if [ $ret -ne 0 ]; then
> +		test_done "$testroot" "$ret"
> +		return 1
> +	fi
> +
> +	echo 'ALPHA' > $testroot/wt/alpha
> +	(cd $testroot/wt && got stage alpha > $testroot/stdout)
> +	ret=$?
> +	if [ $ret -ne 0 ]; then
> +		test_done "$testroot" "$ret"
> +		return 1
> +	fi
> +
> +	echo ' M alpha' > $testroot/stdout.expected
> +	cmp -s $testroot/stdout.expected $testroot/stdout
> +	ret=$?
> +	if [ $ret -ne 0 ]; then
> +		diff -u $testroot/stdout.expected $testroot/stdout
> +		test_done "$testroot" "$ret"
> +		return 1
> +	fi
> +
> +	echo 'alpha' > $testroot/wt/alpha
> +	(cd $testroot/wt && got stage alpha > $testroot/stdout)
> +	ret=$?
> +	if [ $ret -ne 0 ]; then
> +		test_done "$testroot" "$ret"
> +		return 1
> +	fi
> +
> +	echo ' M alpha' > $testroot/stdout.expected
> +	cmp -s $testroot/stdout.expected $testroot/stdout
> +	ret=$?
> +	if [ $ret -ne 0 ]; then
> +		diff -u $testroot/stdout.expected $testroot/stdout
> +		test_done "$testroot" "$ret"
> +		return 1
> +	fi
> +
> +	(cd $testroot/wt && got status > $testroot/stdout)
> +	cmp -s /dev/null $testroot/stdout
> +	ret=$?
> +	if [ $ret -ne 0 ]; then
> +		diff -u /dev/null $testroot/stdout
> +	fi
> +	test_done "$testroot" "$ret"
> +}
> +
>  test_stage_patch_quit() {
>  	local testroot=`test_init stage_patch_quit`
>  
> @@ -2987,6 +3040,7 @@ run_test test_stage_patch_added
>  run_test test_stage_patch_added_twice
>  run_test test_stage_patch_removed
>  run_test test_stage_patch_removed_twice
> +run_test test_stage_patch_reversed
>  run_test test_stage_patch_quit
>  run_test test_stage_patch_incomplete_script
>  run_test test_stage_symlink