Re: [PATCH 3/9] Prepare the builtins for a libified merge_recursive()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Johannes Schindelin <johannes.schindelin@xxxxxx> writes:

> A truly libified function does not die() just for fun.

The sentence is wasting bits.  After all, a helper function in
run-once-and-exit program does not die() just for fun, either.

So what's more interesting to know for the readers?

> As such, the
> recursive merge will convert all die() calls to return -1 instead in the
> next commits, giving the caller a chance at least to print some helpful
> message.
>
> Let's prepare the builtins for this fatal error condition, even if we do
> not really do more than imitating the previous die()'s exit(128): this is
> what callers of e.g. `git merge` have come to expect.

One thing missing is your design decision and justification.

For example, the above explanation hints that the original code in
this hunk expected merge_trees() to die() with some useful message
when there is an error condition, but merge_trees() is going to be
improved not to die() itself and return -1 instead to signal an
error, so that the caller can react more flexibly, and this is a
step to prepare for the version of merge_trees() that no longer
dies.

> -			merge_trees(&o, new->commit->tree, work,
> +			ret = merge_trees(&o, new->commit->tree, work,
>  				old->commit->tree, &result);
> +			if (ret < 0)
> +				exit(128);

The postimage of the patch tells us that the caller is now
responsible for exiting with status 128, but neither the proposed
log message nor the above hunk tells us where the message the
original code must have given to the end user from die() inside
merge_trees().  The updated caller just exits, so a natural guess is
that the calls to die() have been changed to fprintf(stderr) with
the patch.

But that does not mesh very well with the stated objective of the
patch.  The callers want flexibility to do their own error handling,
including giving their own message, so letting merge_trees() to
still write the same message to the standard error stream would not
work well for them.  A caller may want to do merge_trees() just to
see if it succeeds, without wanting to give _any_ indication of that
is happening to the user, because it has an alternate/fallback code
if merge_trees() fails, for example (analogy: "am -3" first tries a
straight patch application before fallking back to 3-way merge; it
may not want to show the error from the first attempt).

The reader _can_ guess that this step ignores the error-message
issue, and improving it later (or keep ignoring that issue) might be
OK in the context of this patch series, but it is necessary to be
upfront to the readers what the design choices were and which one of
those choices the proposed patch adopted as its design for them to
be able to evaluate the patch series correctly.

One design alternative we've seen used in our code to help callers
who want no default messages is to pass struct strbuf &err down the
callchain and collect the default messages without emitting them
directly to the standard error stream when an error is diagnosed.  I
do not know if that pattern is applicable or should be applied to
this codepath.

> Note that the callers of the sequencer (revert and cherry-pick) already
> fail fast even for the return value -1; The only difference is that they
> now get a chance to say "<command> failed".
>
> Signed-off-by: Johannes Schindelin <johannes.schindelin@xxxxxx>
> ---
>  builtin/checkout.c | 4 +++-
>  builtin/merge.c    | 4 ++++
>  sequencer.c        | 4 ++++
>  3 files changed, 11 insertions(+), 1 deletion(-)
>
> diff --git a/builtin/checkout.c b/builtin/checkout.c
> index c3486bd..14312f7 100644
> --- a/builtin/checkout.c
> +++ b/builtin/checkout.c
> @@ -567,8 +567,10 @@ static int merge_working_tree(const struct checkout_opts *opts,
>  			o.ancestor = old->name;
>  			o.branch1 = new->name;
>  			o.branch2 = "local";
> -			merge_trees(&o, new->commit->tree, work,
> +			ret = merge_trees(&o, new->commit->tree, work,
>  				old->commit->tree, &result);
> +			if (ret < 0)
> +				exit(128);
>  			ret = reset_tree(new->commit->tree, opts, 0,
>  					 writeout_error);
>  			if (ret)
> diff --git a/builtin/merge.c b/builtin/merge.c
> index b555a1b..133b853 100644
> --- a/builtin/merge.c
> +++ b/builtin/merge.c
> @@ -682,6 +682,8 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,
>  		hold_locked_index(&lock, 1);
>  		clean = merge_recursive(&o, head,
>  				remoteheads->item, reversed, &result);
> +		if (clean < 0)
> +			exit(128);
>  		if (active_cache_changed &&
>  		    write_locked_index(&the_index, &lock, COMMIT_LOCK))
>  			die (_("unable to write %s"), get_index_file());
> @@ -1550,6 +1552,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
>  		ret = try_merge_strategy(use_strategies[i]->name,
>  					 common, remoteheads,
>  					 head_commit, head_arg);
> +		if (ret < 0)
> +			exit(128);
>  		if (!option_commit && !ret) {
>  			merge_was_ok = 1;
>  			/*
> diff --git a/sequencer.c b/sequencer.c
> index c6362d6..13b794a 100644
> --- a/sequencer.c
> +++ b/sequencer.c
> @@ -293,6 +293,8 @@ static int do_recursive_merge(struct commit *base, struct commit *next,
>  	clean = merge_trees(&o,
>  			    head_tree,
>  			    next_tree, base_tree, &result);
> +	if (clean < 0)
> +		return clean;
>  
>  	if (active_cache_changed &&
>  	    write_locked_index(&the_index, &index_lock, COMMIT_LOCK))
> @@ -561,6 +563,8 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
>  	if (!opts->strategy || !strcmp(opts->strategy, "recursive") || opts->action == REPLAY_REVERT) {
>  		res = do_recursive_merge(base, next, base_label, next_label,
>  					 head, &msgbuf, opts);
> +		if (res < 0)
> +			return res;
>  		write_message(&msgbuf, git_path_merge_msg());
>  	} else {
>  		struct commit_list *common = NULL;
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]