From: Omar Polo Subject: Re: staging the reverse of the staged diff To: Omar Polo Cc: gameoftrees@openbsd.org Date: Fri, 03 Jun 2022 11:50:21 +0200 Omar Polo 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