Message ID | 20230226184354.221-1-andy.koppe@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [v2] restore: fault --staged --worktree with merge opts | expand |
Andy Koppe <andy.koppe@gmail.com> writes: > + /* > + * Reject --staged option to the restore command when combined with > + * merge-related options. Use the accept_ref flag to distinguish it > + * from the checkout command, which does not accept --staged anyway. Understandable. > + * `restore --ours|--theirs --worktree --staged` could mean resolving > + * conflicted paths to one side in both the worktree and the index, > + * but does not currently. Understandable, especially with an understanding that "does not currently" hints our wish to eventually support it. > + * `restore --merge|--conflict=<style>` already recreates conflicts > + * in both the worktree and the index, so adding --staged would be > + * meaningless. And from the same line of reasoning, I do not know if this is a good idea. If "--merge|--conflict=<style>" should recreate conflicts in both when given to "restore --staged --worktree", and if it does so already, then shouldn't it be simply allowed? Why would it be meaningless? Now, it may be understandable to say that it is meaningless to ask merge conflict recreated only in the working tree file but not in the index, or done only in the index but not in the working tree, and erroring out such a request might make sense, but even then, if we do not plan to change the behaviour in the future when "restore --staged --merge" without "--worktree" from what we currently do, I am not sure if it makes sense to error out such a "meaningless" request. Or perhaps I misunderstood the conditional below? > + */ > + if (!opts->accept_ref && opts->checkout_index) { > + if (opts->writeout_stage) > + die(_("'%s' or '%s' cannot be used with %s"), > + "--ours", "--theirs", "--staged"); > > - if (opts->checkout_index && !opts->checkout_worktree && > - opts->merge) > - die(_("'%s' or '%s' cannot be used with %s"), > - "--merge", "--conflict", "--staged"); > + if (opts->merge) > + die(_("'%s' or '%s' cannot be used with %s"), > + "--merge", "--conflict", "--staged"); > + } > diff --git a/t/t2070-restore.sh b/t/t2070-restore.sh > index 7c43ddf1d9..c5d19dd973 100755 > --- a/t/t2070-restore.sh > +++ b/t/t2070-restore.sh > @@ -137,4 +137,20 @@ test_expect_success 'restore --staged invalidates cache tree for deletions' ' > test_must_fail git rev-parse HEAD:new1 > ' > > +test_expect_success 'restore with merge options rejects --staged' ' > + for opts in \ > + "--staged --ours" \ > + "--staged --theirs" \ > + "--staged --merge" \ > + "--staged --conflict=diff3" \ > + "--staged --worktree --ours" \ > + "--staged --worktree --theirs" \ > + "--staged --worktree --merge" \ > + "--staged --worktree --conflict=zdiff3" > + do > + test_must_fail git restore $opts . 2>err && > + grep "cannot be used with --staged" err || return > + done > +' It is quite clear what cases are (and are not) being tested here when written this way. Thanks.
diff --git a/builtin/checkout.c b/builtin/checkout.c index a5155cf55c..17b179a797 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -489,15 +489,28 @@ static int checkout_paths(const struct checkout_opts *opts, die(_("'%s' must be used when '%s' is not specified"), "--worktree", "--source"); - if (opts->checkout_index && !opts->checkout_worktree && - opts->writeout_stage) - die(_("'%s' or '%s' cannot be used with %s"), - "--ours", "--theirs", "--staged"); + /* + * Reject --staged option to the restore command when combined with + * merge-related options. Use the accept_ref flag to distinguish it + * from the checkout command, which does not accept --staged anyway. + * + * `restore --ours|--theirs --worktree --staged` could mean resolving + * conflicted paths to one side in both the worktree and the index, + * but does not currently. + * + * `restore --merge|--conflict=<style>` already recreates conflicts + * in both the worktree and the index, so adding --staged would be + * meaningless. + */ + if (!opts->accept_ref && opts->checkout_index) { + if (opts->writeout_stage) + die(_("'%s' or '%s' cannot be used with %s"), + "--ours", "--theirs", "--staged"); - if (opts->checkout_index && !opts->checkout_worktree && - opts->merge) - die(_("'%s' or '%s' cannot be used with %s"), - "--merge", "--conflict", "--staged"); + if (opts->merge) + die(_("'%s' or '%s' cannot be used with %s"), + "--merge", "--conflict", "--staged"); + } if (opts->patch_mode) { enum add_p_mode patch_mode; diff --git a/t/t2070-restore.sh b/t/t2070-restore.sh index 7c43ddf1d9..c5d19dd973 100755 --- a/t/t2070-restore.sh +++ b/t/t2070-restore.sh @@ -137,4 +137,20 @@ test_expect_success 'restore --staged invalidates cache tree for deletions' ' test_must_fail git rev-parse HEAD:new1 ' +test_expect_success 'restore with merge options rejects --staged' ' + for opts in \ + "--staged --ours" \ + "--staged --theirs" \ + "--staged --merge" \ + "--staged --conflict=diff3" \ + "--staged --worktree --ours" \ + "--staged --worktree --theirs" \ + "--staged --worktree --merge" \ + "--staged --worktree --conflict=zdiff3" + do + test_must_fail git restore $opts . 2>err && + grep "cannot be used with --staged" err || return + done +' + test_done
The 'restore' command already rejects the --merge, --conflict, --ours and --theirs options when combined with --staged, but accepts them when --worktree is added as well. Unfortunately that doesn't appear to do anything useful. The --ours and --theirs options seem to be ignored when both --staged and --worktree are given, whereas with --merge or --conflict, the command has the same effect as if the --staged option wasn't present. So reject those options with '--staged --worktree' as well, using opts->accept_ref to distinguish restore from checkout. Add test for both '--staged' and '--staged --worktree'. Signed-off-by: Andy Koppe <andy.koppe@gmail.com> --- CI: https://github.com/ak2/git/actions/runs/4276063110 builtin/checkout.c | 29 +++++++++++++++++++++-------- t/t2070-restore.sh | 16 ++++++++++++++++ 2 files changed, 37 insertions(+), 8 deletions(-)