Download raw body.
fix staging of multiple files with -p
On Thu, Oct 24, 2019 at 06:18:19PM +0200, Stefan Sperling wrote:
> There's a bug in stage -p where it fails if multiple files are involved.
>
[...]
>
> Based on the above:
>
> 1) If a file has no changes to stage in the -p case, move on to the
> next file instead of reporting an error.
>
> 2) If there is nothing to stage (with or without -p), print an error
> and use an exit code != 0. The related test failed to take the exit
> code into account, fix this.
>
> ok?
the rational is good. the diff seems ok too.
ok semarie@
> diff a926e3a4334151b10e2b78e1fa3f2a59a44c71f2 /home/stsp/src/got
> blob - 3c6178de57a898b1c3c7be0e3585e0a5c40bb6bb
> file + lib/worktree.c
> --- lib/worktree.c
> +++ lib/worktree.c
> @@ -5871,7 +5871,8 @@ check_stage_ok(void *arg, unsigned char status,
> struct got_object_id *base_commit_idp = NULL;
> char *in_repo_path = NULL, *p;
>
> - if (status == GOT_STATUS_UNVERSIONED)
> + if (status == GOT_STATUS_UNVERSIONED ||
> + status == GOT_STATUS_NO_CHANGE)
> return NULL;
> if (status == GOT_STATUS_NONEXISTENT)
> return got_error_set_errno(ENOENT, relpath);
> @@ -5891,10 +5892,7 @@ check_stage_ok(void *arg, unsigned char status,
> base_commit_idp = &base_commit_id;
> }
>
> - if (status == GOT_STATUS_NO_CHANGE) {
> - err = got_error_path(ie->path, GOT_ERR_STAGE_NO_CHANGE);
> - goto done;
> - } else if (status == GOT_STATUS_CONFLICT) {
> + if (status == GOT_STATUS_CONFLICT) {
> err = got_error_path(ie->path, GOT_ERR_STAGE_CONFLICT);
> goto done;
> } else if (status != GOT_STATUS_ADD &&
> @@ -5925,6 +5923,7 @@ struct stage_path_arg {
> void *status_arg;
> got_worktree_patch_cb patch_cb;
> void *patch_arg;
> + int staged_something;
> };
>
> static const struct got_error *
> @@ -5983,6 +5982,7 @@ stage_path(void *arg, unsigned char status,
> else
> stage = GOT_FILEIDX_STAGE_MODIFY;
> got_fileindex_entry_stage_set(ie, stage);
> + a->staged_something = 1;
> if (a->status_cb == NULL)
> break;
> err = (*a->status_cb)(a->status_arg, GOT_STATUS_NO_CHANGE,
> @@ -6007,13 +6007,13 @@ stage_path(void *arg, unsigned char status,
> }
> stage = GOT_FILEIDX_STAGE_DELETE;
> got_fileindex_entry_stage_set(ie, stage);
> + a->staged_something = 1;
> if (a->status_cb == NULL)
> break;
> err = (*a->status_cb)(a->status_arg, GOT_STATUS_NO_CHANGE,
> get_staged_status(ie), relpath, NULL, NULL, NULL);
> break;
> case GOT_STATUS_NO_CHANGE:
> - err = got_error_path(relpath, GOT_ERR_STAGE_NO_CHANGE);
> break;
> case GOT_STATUS_CONFLICT:
> err = got_error_path(relpath, GOT_ERR_STAGE_CONFLICT);
> @@ -6089,11 +6089,16 @@ got_worktree_stage(struct got_worktree *worktree,
> spa.patch_arg = patch_arg;
> spa.status_cb = status_cb;
> spa.status_arg = status_arg;
> + spa.staged_something = 0;
> TAILQ_FOREACH(pe, paths, entry) {
> err = worktree_status(worktree, pe->path, fileindex, repo,
> stage_path, &spa, NULL, NULL);
> if (err)
> goto done;
> + }
> + if (!spa.staged_something) {
> + err = got_error(GOT_ERR_STAGE_NO_CHANGE);
> + goto done;
> }
>
> sync_err = sync_fileindex(fileindex, fileindex_path);
> blob - ba1b5eaaf04bac104befb9a8defef1522ad1de37
> file + regress/cmdline/stage.sh
> --- regress/cmdline/stage.sh
> +++ regress/cmdline/stage.sh
> @@ -352,7 +352,7 @@ function test_double_stage {
> (cd $testroot/wt && got add foo > /dev/null)
> (cd $testroot/wt && got stage alpha beta foo > /dev/null)
>
> - echo "got: alpha: no changes to stage" > $testroot/stderr.expected
> + echo "got: no changes to stage" > $testroot/stderr.expected
> (cd $testroot/wt && got stage alpha 2> $testroot/stderr)
> cmp -s $testroot/stderr.expected $testroot/stderr
> ret="$?"
> @@ -362,10 +362,39 @@ function test_double_stage {
> return 1
> fi
>
> - (cd $testroot/wt && got stage beta > $testroot/stdout)
> + (cd $testroot/wt && got stage beta \
> + > $testroot/stdout 2> $testroot/stderr)
> ret="$?"
> + if [ "$ret" == "0" ]; then
> + echo "got stage command succeeded unexpectedly" >&2
> + test_done "$testroot" "1"
> + return 1
> + fi
> + echo -n > $testroot/stdout.expected
> + cmp -s $testroot/stdout.expected $testroot/stdout
> + ret="$?"
> if [ "$ret" != "0" ]; then
> - echo "got stage command failed unexpectedly" >&2
> + diff -u $testroot/stdout.expected $testroot/stdout
> + test_done "$testroot" "$ret"
> + return 1
> + fi
> +
> + echo "got: no changes to stage" > $testroot/stderr.expected
> + (cd $testroot/wt && got stage foo 2> $testroot/stderr)
> + cmp -s $testroot/stderr.expected $testroot/stderr
> + ret="$?"
> + if [ "$ret" != "0" ]; then
> + diff -u $testroot/stderr.expected $testroot/stderr
> + test_done "$testroot" "$ret"
> + return 1
> + fi
> +
> + printf "q\n" > $testroot/patchscript
> + (cd $testroot/wt && got stage -F $testroot/patchscript -p \
> + > $testroot/stdout 2> $testroot/stderr)
> + ret="$?"
> + if [ "$ret" == "0" ]; then
> + echo "got stage command succeeded unexpectedly" >&2
> test_done "$testroot" "1"
> return 1
> fi
> @@ -378,7 +407,7 @@ function test_double_stage {
> return 1
> fi
>
> - echo "got: foo: no changes to stage" > $testroot/stderr.expected
> + echo "got: no changes to stage" > $testroot/stderr.expected
> (cd $testroot/wt && got stage foo 2> $testroot/stderr)
> cmp -s $testroot/stderr.expected $testroot/stderr
> ret="$?"
> @@ -1421,10 +1450,10 @@ function test_stage_patch {
> # don't stage any hunks
> printf "n\nn\nn\n" > $testroot/patchscript
> (cd $testroot/wt && got stage -F $testroot/patchscript -p \
> - numbers > $testroot/stdout)
> + numbers > $testroot/stdout 2> $testroot/stderr)
> ret="$?"
> - if [ "$ret" != "0" ]; then
> - echo "got stage command failed unexpectedly" >&2
> + if [ "$ret" == "0" ]; then
> + echo "got stage command succeeded unexpectedly" >&2
> test_done "$testroot" "1"
> return 1
> fi
> @@ -1472,6 +1501,16 @@ EOF
> return 1
> fi
>
> + echo "got: no changes to stage" > $testroot/stderr.expected
> + cmp -s $testroot/stderr.expected $testroot/stderr
> + ret="$?"
> + if [ "$ret" != "0" ]; then
> + diff -u $testroot/stderr.expected $testroot/stderr
> + test_done "$testroot" "$ret"
> + return 1
> + fi
> +
> +
> (cd $testroot/wt && got status > $testroot/stdout)
> echo "M numbers" > $testroot/stdout.expected
> cmp -s $testroot/stdout.expected $testroot/stdout
> @@ -1968,7 +2007,7 @@ function test_stage_patch_added_twice {
> return 1
> fi
>
> - echo "got: epsilon/new: no changes to stage" > $testroot/stderr.expected
> + echo "got: no changes to stage" > $testroot/stderr.expected
> cmp -s $testroot/stderr.expected $testroot/stderr
> ret="$?"
> if [ "$ret" != "0" ]; then
> @@ -2087,13 +2126,13 @@ function test_stage_patch_removed_twice {
> (cd $testroot/wt && got stage -F $testroot/patchscript -p beta \
> > $testroot/stdout 2> $testroot/stderr)
> ret="$?"
> - if [ "$ret" != "0" ]; then
> - echo "got stage command failed unexpectedly" >&2
> + if [ "$ret" == "0" ]; then
> + echo "got stage command succeeded unexpectedly" >&2
> test_done "$testroot" "$ret"
> return 1
> fi
>
> - echo -n > $testroot/stderr.expected
> + echo "got: no changes to stage" > $testroot/stderr.expected
> cmp -s $testroot/stderr.expected $testroot/stderr
> ret="$?"
> if [ "$ret" != "0" ]; then
>
--
Sebastien Marie
fix staging of multiple files with -p