On 08/08, Paul-Sebastian Ungureanu wrote:
> Currently, `show_stash()` uses `cmd_diff()` to generate
> the output. After this commit, the output will be generated
> using the internal API.
> 
> Before this commit, `git stash show --quiet` would act like
> `git diff` and error out if the stash is not empty. Now, the
> `--quiet` option does not error out given an empty stash.

I think this needs a bit more justification.  As I mentioned in my
comment to a previous patch, I'm not sure '--quiet' makes much sense
with 'git stash show' (it will show nothing, and will always exit with
an error code, as the stash will always contain something), but if we
are supporting the same flags as 'git diff', and essentially just
forwarding them, shouldn't they keep the same behaviour as well?

> Signed-off-by: Paul-Sebastian Ungureanu <ungureanupaulsebast...@gmail.com>
> ---
>  builtin/stash--helper.c | 73 +++++++++++++++++++++++++----------------
>  1 file changed, 45 insertions(+), 28 deletions(-)
> 
> diff --git a/builtin/stash--helper.c b/builtin/stash--helper.c
> index 0c1efca6b..ec8c38c6f 100644
> --- a/builtin/stash--helper.c
> +++ b/builtin/stash--helper.c
> @@ -10,6 +10,8 @@
>  #include "run-command.h"
>  #include "dir.h"
>  #include "rerere.h"
> +#include "revision.h"
> +#include "log-tree.h"
>  
>  static const char * const git_stash_helper_usage[] = {
>       N_("git stash--helper list [<options>]"),
> @@ -662,56 +664,71 @@ static int git_stash_config(const char *var, const char 
> *value, void *cb)
>  
>  static int show_stash(int argc, const char **argv, const char *prefix)
>  {
> -     int i, ret = 0;
> -     struct child_process cp = CHILD_PROCESS_INIT;
> -     struct argv_array args_refs = ARGV_ARRAY_INIT;
> +     int i;
> +     int flags = 0;
>       struct stash_info info;
> +     struct rev_info rev;
> +     struct argv_array stash_args = ARGV_ARRAY_INIT;
>       struct option options[] = {
>               OPT_END()
>       };
>  
> -     argc = parse_options(argc, argv, prefix, options,
> -                          git_stash_helper_show_usage,
> -                          PARSE_OPT_KEEP_UNKNOWN);
> +     init_diff_ui_defaults();
> +     git_config(git_diff_ui_config, NULL);
>  
> -     cp.git_cmd = 1;
> -     argv_array_push(&cp.args, "diff");
> +     init_revisions(&rev, prefix);
>  
> -     /* Push arguments which are not options into args_refs. */
> -     for (i = 0; i < argc; ++i) {
> -             if (argv[i][0] == '-')
> -                     argv_array_push(&cp.args, argv[i]);
> +     /* Push arguments which are not options into stash_args. */
> +     for (i = 1; i < argc; ++i) {
> +             if (argv[i][0] != '-')
> +                     argv_array_push(&stash_args, argv[i]);
>               else
> -                     argv_array_push(&args_refs, argv[i]);
> -     }
> -
> -     if (get_stash_info(&info, args_refs.argc, args_refs.argv)) {
> -             child_process_clear(&cp);
> -             argv_array_clear(&args_refs);
> -             return -1;
> +                     flags++;
>       }
>  
>       /*
>        * The config settings are applied only if there are not passed
>        * any flags.
>        */
> -     if (cp.args.argc == 1) {
> +     if (!flags) {
>               git_config(git_stash_config, NULL);
>               if (show_stat)
> -                     argv_array_push(&cp.args, "--stat");
> +                     rev.diffopt.output_format |= DIFF_FORMAT_DIFFSTAT;
> +             if (show_patch) {
> +                     rev.diffopt.output_format = ~DIFF_FORMAT_NO_OUTPUT;
> +                     rev.diffopt.output_format |= DIFF_FORMAT_PATCH;
> +             }

I failed to notice this in the previous patch (the problem existed
there as well), but this changes the behaviour of 'git -c
stash.showStat=false stash show <stash>'.  Previously doing this would
not show anything, which is the correct behaviour, while now still
shows the diffstat.

I think the show_stat variable is interpreted the wrong way around in
the previous patch.

Something else I noticed now that I was playing around more with the
config options is that the parsing of the config options is not
correctly done in the previous patch.  It does a 'strcmp(var,
"stash.showStat"))', but the config API makes all variables lowercase
(config options are case insensitive, and making everything lowercase
is the way to ensure that), so it should be 'strcmp(var, "stash.showstat"))', 
and similar for the 'stash.showpatch' config option.

This all sounds like it would be nice to have some tests for these
config options, to make sure we get it right, and won't break them in
the future.

> +     }
>  
> -             if (show_patch)
> -                     argv_array_push(&cp.args, "-p");
> +     if (get_stash_info(&info, stash_args.argc, stash_args.argv)) {
> +             argv_array_clear(&stash_args);
> +             return -1;
>       }
>  
> -     argv_array_pushl(&cp.args, oid_to_hex(&info.b_commit),
> -                      oid_to_hex(&info.w_commit), NULL);
> +     argc = setup_revisions(argc, argv, &rev, NULL);
> +     if (!rev.diffopt.output_format)
> +             rev.diffopt.output_format = DIFF_FORMAT_PATCH;
> +     diff_setup_done(&rev.diffopt);
> +     rev.diffopt.flags.recursive = 1;
> +     setup_diff_pager(&rev.diffopt);
>  
> -     ret = run_command(&cp);
> +     /*
> +      * We can return early if there was any option not recognised by
> +      * `diff_opt_parse()`, besides the word `stash`.
> +      */

I'm not sure I follow what you mean with this comment.  I don't see
any 'diff_opt_parse' in the code above?  

> +     if (argc > 1) {
> +             free_stash_info(&info);
> +             argv_array_clear(&stash_args);
> +             usage_with_options(git_stash_helper_show_usage, options);
> +     }
> +
> +     /* Do the diff thing. */

This comment should be dropped.  It's obvious that we are doing the
diff thing below from the code, so the comment is redundant at best,
makes people read more lines, and could possibly get outdated.

I'd also drop the other comments above, as they do not provide a lot
of extra value imho.

> +     diff_tree_oid(&info.b_commit, &info.w_commit, "", &rev.diffopt);
> +     log_tree_diff_flush(&rev);
>  
>       free_stash_info(&info);
> -     argv_array_clear(&args_refs);
> -     return ret;
> +     argv_array_clear(&stash_args);
> +     return 0;
>  }
>  
>  int cmd_stash__helper(int argc, const char **argv, const char *prefix)
> -- 
> 2.18.0.573.g56500d98f
> 

Reply via email to