git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Johannes Schindelin <Johannes.Schindelin@gmx.de>
To: Christian Couder <christian.couder@gmail.com>
Cc: Miriam Rubio <mirucam@gmail.com>, git <git@vger.kernel.org>,
	Pranit Bauva <pranit.bauva@gmail.com>,
	Lars Schneider <larsxschneider@gmail.com>,
	Christian Couder <chriscool@tuxfamily.org>,
	Tanushree Tumane <tanushreetumane@gmail.com>
Subject: Re: [PATCH 12/29] bisect--helper: reimplement `bisect_next` and `bisect_auto_next` shell functions in C
Date: Mon, 17 Feb 2020 23:00:55 +0100 (CET)	[thread overview]
Message-ID: <nycvar.QRO.7.76.6.2002172245430.46@tvgsbejvaqbjf.bet> (raw)
In-Reply-To: <CAP8UFD1UBPwYLUEdUJj3k1Yj0Y9dD6RyGh1dFL=wsSNihErqZQ@mail.gmail.com>

Hi Chris,

On Mon, 17 Feb 2020, Christian Couder wrote:

> On Thu, Jan 30, 2020 at 11:47 PM Johannes Schindelin
> <Johannes.Schindelin@gmx.de> wrote:
> >
> > On Mon, 20 Jan 2020, Miriam Rubio wrote:
>
> > > +static void prepare_rev_argv(struct bisect_terms *terms, struct argv_array *rev_argv)> > +{
> > > +     struct string_list good_revs = STRING_LIST_INIT_DUP;
> > > +     char *term_good = xstrfmt("%s-*", terms->term_good);
> > > +
> > > +     for_each_glob_ref_in(register_good_ref, term_good,
> > > +                          "refs/bisect/", &good_revs);
> > > +
> > > +     argv_array_pushl(rev_argv, "skipped_commits", "refs/bisect/bad", "--not", NULL);
> > > +     for (int i = 0; i < good_revs.nr; i++)
> > > +             argv_array_push(rev_argv, good_revs.items[i].string);
> > > +
> > > +     string_list_clear(&good_revs, 0);
> > > +     free(term_good);
> > > +}
> >
> > Maybe we should fold that into `prepare_revs()`? We could then render the
> > arguments directly into `revs` (via `add_pending_object()`, after setting
> > obj->flags |= UNINTERESTING`) rather than formatting them into a string
> > list, then deep-copy them into an `argv_array` only to parse them back
> > into OIDs that we already had in the first place.
>
> The current code is a straightforward port from shell. If we do what
> you suggest, yeah, it will be less wasteful, but on the other hand it
> will be less easy to see that we are doing a good job of properly
> porting code from shell.

If you reason that way, you will have to use tons of `run_command()` calls
to translate the shell code as verbatim as possible.

However, as you can see from our commit history, we do not do that.
Instead, we use the more powerful expressiveness of C to come up with more
elegant code than to slavishly convert shell code to inelegant C code.

> I suggest we try to focus on the later rather than the former right now,
> especially as performance is not very important here.

Oh, but my comment was totally not about performance, and pretty much
exclusively about readability.

If Miriam goes with my suggestion, it will result in more readable code
that is easier to review and therefore much more likely to be free of
unintentional bugs.

> Using small functions also makes it easy to see that we are properly
> releasing memory. A previous version of this code had everything into
> a big function that used goto statements and it was less clear that we
> released everything.

If you want to make it easier to avoid double-free()s and memory leaks, I
am a bit puzzled how you want to claim that the current "we're copying the
strings so often that pretty much everybody loses track of them" approach
should be superior to adding the strings once, and once only, to a string
array.

> > > +static int bisect_skipped_commits(struct bisect_terms *terms)
> > > +{
> > > +     int res = 0;
> > > +     FILE *fp = NULL;
> > > +     struct rev_info revs;
> > > +
> > > +     fp = fopen(git_path_bisect_log(), "a");
> > > +     if (!fp)
> > > +             return error_errno(_("could not open '%s' for appending"),
> > > +                               git_path_bisect_log());
> > > +
> > > +     res = prepare_revs(terms, &revs);
> > > +
> > > +     if (!res)
> > > +             res = process_skipped_commits(fp, terms, &revs);
> > > +
> > > +     fclose(fp);
> > > +     return res;
> > > +}
> >
> > This is again a very short wrapper around another function, so it will
> > probably make sense to merge the two, otherwise the boilerplate might very
> > well outweigh the actual code doing actual work.
>
> Yeah, there is perhaps a significant amount of boiler plate, but the
> code is much easier to check for leaks than when everything was in the
> same big function and there were goto statements, so I think it's a
> reasonable trade-off

Given this snippet, I would strongly disagree with this assessment:

    fp = fopen(git_path_bisect_log(), "a");
    if (!fp)
            res = error_errno(_("could not open '%s' for appending"),
                              git_path_bisect_log());
    else
            res = prepare_revs(terms, &revs);

    if (!res)
            res = process_skipped_commits(fp, terms, &revs);

    if (fp)
            fclose(fp);

There is positively no need for a `goto` whatsoever.

> > > +             fclose(fp);
> > > +     } else {
> > > +             res = error_errno(_("could not open '%s' for "
> > > +                                 "appending"),
> > > +                               git_path_bisect_log());
> > > +     }
> >
> > This pattern of opening a file, writing something into it, and then return
> > success, otherwise failure, seems like a repeated pattern. In other words,
> > it would be a good candidate for factoring out into its own function.
>
> Yeah, but it seems that in this patch series we use the pattern only
> once. So I think it's fair to leave that for another patch series with
> cleanups and performance improvements or perhaps for microprojects.

Sure, we could repeat past mistakes in this patch series, too.

If, on the other hand, we use this patch series as "an excuse" to
introduce such a helper, no future patch series will have to use the same
kind of argument as you just offered. Instead, we will have an improved
API that will help not only this patch series, but many more to come.

There is tons of precedent for this kind of thing, where we add an
introductory patch at the beginning of a patch series, factoring out
already-existing code into a more reusable shape, and then use it.

So why not repeat that pattern and do the same thing here?

Ciao,
Johannes

  reply	other threads:[~2020-02-17 22:01 UTC|newest]

Thread overview: 54+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-01-20 14:37 [Outreachy][PATCH 00/29] Finish converting git bisect to C part 1 Miriam Rubio
2020-01-20 14:37 ` [PATCH 01/29] bisect--helper: convert `vocab_*` char pointers to char arrays Miriam Rubio
2020-01-20 14:37 ` [PATCH 02/29] bisect--helper: change `retval` to `res` Miriam Rubio
2020-01-20 14:37 ` [PATCH 03/29] bisect: use the standard 'if (!var)' way to check for 0 Miriam Rubio
2020-01-20 14:37 ` [PATCH 04/29] run-command: make `exists_in_PATH()` non-static Miriam Rubio
2020-01-20 14:37 ` [PATCH 05/29] bisect--helper: introduce new `decide_next()` function Miriam Rubio
2020-01-20 14:37 ` [PATCH 06/29] bisect: libify `exit_if_skipped_commits` to `error_if_skipped*` and its dependents Miriam Rubio
2020-01-20 21:57   ` Johannes Schindelin
2020-01-21  6:40     ` Christian Couder
2020-01-21 10:00       ` Miriam R.
2020-01-20 14:37 ` [PATCH 07/29] bisect: libify `bisect_checkout` Miriam Rubio
2020-01-20 14:37 ` [PATCH 08/29] bisect: libify `check_merge_bases` and its dependents Miriam Rubio
2020-01-20 22:09   ` Johannes Schindelin
2020-01-21  9:59     ` Miriam R.
2020-01-20 14:37 ` [PATCH 09/29] bisect: libify `check_good_are_ancestors_of_bad` " Miriam Rubio
2020-01-20 22:20   ` Johannes Schindelin
2020-01-21  6:59     ` Christian Couder
2020-01-21 10:00       ` Miriam R.
2020-01-20 14:37 ` [PATCH 10/29] bisect: libify `handle_bad_merge_base` " Miriam Rubio
2020-01-20 22:23   ` Johannes Schindelin
2020-01-21  7:05     ` Christian Couder
2020-01-21 10:00       ` Miriam R.
2020-01-20 14:37 ` [PATCH 11/29] bisect: libify `bisect_next_all` Miriam Rubio
2020-01-20 22:29   ` Johannes Schindelin
2020-01-21  7:15     ` Christian Couder
2020-01-30 15:18       ` Johannes Schindelin
2020-01-20 14:37 ` [PATCH 12/29] bisect--helper: reimplement `bisect_next` and `bisect_auto_next` shell functions in C Miriam Rubio
2020-01-30 22:47   ` Johannes Schindelin
2020-01-31 10:53     ` Miriam R.
2020-02-17  7:20     ` Christian Couder
2020-02-17 22:00       ` Johannes Schindelin [this message]
2020-01-20 14:37 ` [PATCH 13/29] bisect--helper: finish porting `bisect_start()` to C Miriam Rubio
2020-01-20 14:37 ` [PATCH 14/29] bisect--helper: retire `--bisect-clean-state` subcommand Miriam Rubio
2020-01-20 14:37 ` [PATCH 15/29] bisect--helper: retire `--next-all` subcommand Miriam Rubio
2020-01-20 14:37 ` [PATCH 16/29] bisect--helper: reimplement `bisect_autostart` shell function in C Miriam Rubio
2020-01-20 14:37 ` [PATCH 17/29] bisect--helper: reimplement `bisect_state` & `bisect_head` shell functions " Miriam Rubio
2020-01-20 14:37 ` [PATCH 18/29] bisect--helper: retire `--check-expected-revs` subcommand Miriam Rubio
2020-01-20 14:37 ` [PATCH 19/29] bisect--helper: retire `--write-terms` subcommand Miriam Rubio
2020-01-20 14:37 ` [PATCH 20/29] bisect--helper: reimplement `bisect_log` shell function in C Miriam Rubio
2020-01-20 14:37 ` [PATCH 21/29] bisect--helper: reimplement `bisect_replay` " Miriam Rubio
2020-01-20 14:37 ` [PATCH 22/29] bisect--helper: retire `--bisect-write` subcommand Miriam Rubio
2020-01-20 14:37 ` [PATCH 23/29] bisect--helper: use `res` instead of return in BISECT_RESET case option Miriam Rubio
2020-01-20 14:37 ` [PATCH 24/29] bisect--helper: retire `--bisect-autostart` subcommand Miriam Rubio
2020-01-20 14:37 ` [PATCH 25/29] bisect--helper: retire `--bisect-auto-next` subcommand Miriam Rubio
2020-01-20 14:37 ` [PATCH 26/29] bisect--helper: reimplement `bisect_skip` shell function in C Miriam Rubio
2020-01-20 14:37 ` [PATCH 27/29] bisect--helper: retire `--check-and-set-terms` subcommand Miriam Rubio
2020-01-20 14:37 ` [PATCH 28/29] bisect--helper: reimplement `bisect_visualize()`shell function in C Miriam Rubio
2020-01-20 14:38 ` [PATCH 29/29] bisect--helper: reimplement `bisect_run` shell " Miriam Rubio
2020-01-20 21:41 ` [Outreachy][PATCH 00/29] Finish converting git bisect to C part 1 Johannes Schindelin
2020-01-20 23:24   ` Christian Couder
2020-01-30 15:12     ` Johannes Schindelin
2020-01-30 21:12       ` Junio C Hamano
2020-01-21  8:44   ` Miriam R.
2020-01-30 15:13     ` Johannes Schindelin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=nycvar.QRO.7.76.6.2002172245430.46@tvgsbejvaqbjf.bet \
    --to=johannes.schindelin@gmx.de \
    --cc=chriscool@tuxfamily.org \
    --cc=christian.couder@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=larsxschneider@gmail.com \
    --cc=mirucam@gmail.com \
    --cc=pranit.bauva@gmail.com \
    --cc=tanushreetumane@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).