All of lore.kernel.org
 help / color / mirror / Atom feed
From: Paul Tan <pyokagan@gmail.com>
To: Johannes Schindelin <johannes.schindelin@gmx.de>
Cc: Git List <git@vger.kernel.org>, Stefan Beller <sbeller@google.com>
Subject: Re: [PATCH/WIP v3 04/31] am: implement patch queue mechanism
Date: Thu, 25 Jun 2015 23:16:18 +0800	[thread overview]
Message-ID: <CACRoPnSZn=8keW3meUvLY-B_4vQigMTQW_VVvY2rU8ctjcxcaQ@mail.gmail.com> (raw)
In-Reply-To: <6560adbc8b1842dd369628980f1264c3@www.dscho.org>

On Wed, Jun 24, 2015 at 10:59 PM, Johannes Schindelin
<johannes.schindelin@gmx.de> wrote:
>> diff --git a/builtin/am.c b/builtin/am.c
>> index dbc8836..af68c51 100644
>> --- a/builtin/am.c
>> +++ b/builtin/am.c
>> @@ -6,6 +6,158 @@
>>  #include "cache.h"
>>  #include "builtin.h"
>>  #include "exec_cmd.h"
>> +#include "parse-options.h"
>> +#include "dir.h"
>> +
>> +struct am_state {
>> +     /* state directory path */
>> +     struct strbuf dir;
>> +
>> +     /* current and last patch numbers, 1-indexed */
>> +     int cur;
>> +     int last;
>> +};
>> +
>> +/**
>> + * Initializes am_state with the default values.
>> + */
>> +static void am_state_init(struct am_state *state)
>> +{
>> +     memset(state, 0, sizeof(*state));
>> +
>> +     strbuf_init(&state->dir, 0);
>> +}
>
> With strbufs, we use the initializer STRBUF_INIT. How about using
>
> #define AM_STATE_INIT { STRBUF_INIT, 0, 0 }
>
> here?

Later in the patch series am_state_init() will also take into account
config settings when filling up the default values. e.g. see patches
25/31[1] or 31/31[2]. I think that is reasonable: the purpose of
am_state_init() is to initialize the am_state struct with the default
values, and the default values can be set by the user through the
config settings.

This means, though, that we can't use initializers without introducing
global variables.

[1] http://thread.gmane.org/gmane.comp.version-control.git/271967/focus=271972
[2] http://thread.gmane.org/gmane.comp.version-control.git/271967/focus=271972

>> +/**
>> + * Reads the contents of `file`. The third argument can be used to give a hint
>> + * about the file size, to avoid reallocs. Returns number of bytes read on
>> + * success, -1 if the file does not exist. If trim is set, trailing whitespace
>> + * will be removed from the file contents.
>> + */
>> +static int read_state_file(struct strbuf *sb, const char *file,
>> size_t hint, int trim)
>> +{
>> +     strbuf_reset(sb);
>> +     if (strbuf_read_file(sb, file, hint) >= 0) {
>> +             if (trim)
>> +                     strbuf_trim(sb);
>> +
>> +             return sb->len;
>> +     }
>> +
>> +     if (errno == ENOENT)
>> +             return -1;
>> +
>> +     die_errno(_("could not read '%s'"), file);
>> +}
>
> A couple of thoughts:
>
> - why not reuse the strbuf by making it a part of the am_state()? That way, you can allocate, say, 1024 bytes (should be plenty enough for most of our operations) and just reuse them in all of the functions. We will not make any of this multi-threaded anyway, I don't think.

But too much usage of this temporary strbuf may lead to a situation
where one function calls another, and both functions write to the
strbuf and clobber its contents.

Besides, if we are talking about read_state_file(), it takes an
external strbuf, so it gives the caller the freedom to choose which
strbuf it uses (e.g. if it is stack allocated or in the am_state
struct). I think it's more flexible this way.

> - Given that we only read short files all the time, why not skip the hint parameter? Especially if we reuse the strbuf, it should be good enough to allocate a reasonable buffer first and then just assume that we do not have to reallocate it all that often anyway.

Doh! Right, the hint parameter is quite useless, since in am_load() we
use the same strbuf anyway. (And strbuf_init() can set a hint as well)
I've removed it on my side.

> - Since we only read files from the state directory, why not pass the basename as parameter? That way we can avoid calling `am_path()` explicitly over and over again (and yours truly cannot forget to call `am_path()` in future patches).

Makes sense. After all, this function is called read_STATE_file() ;-)

> - If you agree with these suggestions, the signature would become something like
>
> static void read_state_file(struct am_state *state, const char *basename, int trim);

So for now, my function signature is

static void read_state_file(struct strbuf *sb, const struct am_state
*state, const char *basename, int trim);

>> +/**
>> + * Remove the am_state directory.
>> + */
>> +static void am_destroy(const struct am_state *state)
>> +{
>> +     struct strbuf sb = STRBUF_INIT;
>> +
>> +     strbuf_addstr(&sb, state->dir.buf);
>> +     remove_dir_recursively(&sb, 0);
>> +     strbuf_release(&sb);
>> +}
>
> Given that `remove_dir_recursively()` has to reset the strbuf with the directory's path to the original value before it returns (because it recurses into itself, therefore the value *has* to be reset when returning), we can just call
>
>     remove_dir_recursively(&state->dir, 0);
>
> and do not need another temporary strbuf.

Ah right. Although, state->dir is not an strbuf anymore on my side. As
Junio[3] rightfully noted, state->dir is not modified by the am_*()
API, so it's been changed to a char*. Which means an strbuf is
required to be passed to remove_dir_recursively();

>> +/**
>> + * Increments the patch pointer, and cleans am_state for the application of the
>> + * next patch.
>> + */
>> +static void am_next(struct am_state *state)
>> +{
>> +     state->cur++;
>> +     write_file(am_path(state, "next"), 1, "%d", state->cur);
>> +}
>
> Locking and re-checking the contents of "next" before writing the incremented value would probably be a little too paranoid...

Yeah, Junio did bring something like that[3]. I'm still thinking about
it, though I don't think I would like this issue to block the patch
series since it's a delicate issue, and git-am.sh does not do anything
special either.

For now though, I've moved all the write_file()s into a central
am_save() function, so if we want to do any locking or syncing it
would be easy to modify am_save(), and then all the callers will
benefit.

[3] http://thread.gmane.org/gmane.comp.version-control.git/271967/focus=271972

  reply	other threads:[~2015-06-25 15:16 UTC|newest]

Thread overview: 64+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-06-18 11:25 [PATCH/WIP v3 00/31] Make git-am a builtin Paul Tan
2015-06-18 11:25 ` [PATCH/WIP v3 01/31] wrapper: implement xopen() Paul Tan
2015-06-24 16:28   ` Johannes Schindelin
2015-06-24 16:59     ` Stefan Beller
2015-06-24 18:39       ` Johannes Schindelin
2015-07-01  9:41         ` Paul Tan
2015-07-01  9:53           ` Paul Tan
2015-06-18 11:25 ` [PATCH/WIP v3 02/31] wrapper: implement xfopen() Paul Tan
2015-06-18 11:25 ` [PATCH/WIP v3 03/31] am: implement skeletal builtin am Paul Tan
2015-06-18 20:26   ` Junio C Hamano
2015-06-19  9:56     ` Paul Tan
2015-06-18 11:25 ` [PATCH/WIP v3 04/31] am: implement patch queue mechanism Paul Tan
2015-06-18 17:47   ` Stefan Beller
2015-06-18 20:43   ` Junio C Hamano
2015-06-19 12:49     ` Paul Tan
2015-06-24 14:59   ` Johannes Schindelin
2015-06-25 15:16     ` Paul Tan [this message]
2015-06-18 11:25 ` [PATCH/WIP v3 05/31] am: split out mbox/maildir patches with git-mailsplit Paul Tan
2015-06-18 20:52   ` Junio C Hamano
2015-06-18 11:25 ` [PATCH/WIP v3 06/31] am: detect mbox patches Paul Tan
2015-06-18 21:02   ` Junio C Hamano
2015-06-24  8:41     ` Paul Tan
2015-06-24 15:10   ` Johannes Schindelin
2015-06-25 13:40     ` Paul Tan
2015-06-26  7:42       ` Paul Tan
2015-06-18 11:25 ` [PATCH/WIP v3 07/31] am: extract patch, message and authorship with git-mailinfo Paul Tan
2015-06-18 21:10   ` Junio C Hamano
2015-06-19  9:22     ` Paul Tan
2015-06-19 16:13       ` Junio C Hamano
2015-06-24  7:54         ` Paul Tan
2015-06-24 15:59           ` Junio C Hamano
2015-06-25 11:54             ` Paul Tan
     [not found]       ` <CAPc5daVbpB_T4cY1xvLrBKPUZw0JNMXqNAOsKE-R7NPO2nrnZA@mail.gmail.com>
2015-06-19 16:15         ` Paul Tan
2015-06-19 20:12           ` Johannes Schindelin
2015-06-24 16:36   ` Johannes Schindelin
2015-06-26  8:11     ` Paul Tan
2015-06-26 20:41       ` Junio C Hamano
2015-06-18 11:25 ` [PATCH/WIP v3 08/31] am: apply patch with git-apply Paul Tan
2015-06-18 21:23   ` Junio C Hamano
2015-06-18 11:25 ` [PATCH/WIP v3 09/31] am: commit applied patch Paul Tan
2015-06-18 11:25 ` [PATCH/WIP v3 10/31] am: refresh the index at start Paul Tan
2015-06-18 21:28   ` Junio C Hamano
2015-06-19  8:07     ` Paul Tan
2015-06-18 11:25 ` [PATCH/WIP v3 11/31] am: refuse to apply patches if index is dirty Paul Tan
2015-06-18 11:25 ` [PATCH/WIP v3 12/31] am: implement --resolved/--continue Paul Tan
2015-06-18 11:25 ` [PATCH/WIP v3 13/31] am: implement --skip Paul Tan
2015-06-18 11:25 ` [PATCH/WIP v3 14/31] am: implement --abort Paul Tan
2015-06-18 11:25 ` [PATCH/WIP v3 15/31] am: don't accept patches when there's a session in progress Paul Tan
2015-06-18 11:25 ` [PATCH/WIP v3 16/31] am: implement quiet option Paul Tan
2015-06-18 11:25 ` [PATCH/WIP v3 17/31] am: exit with user friendly message on patch failure Paul Tan
2015-06-18 11:25 ` [PATCH/WIP v3 18/31] am: implement am --signoff Paul Tan
2015-06-18 11:25 ` [PATCH/WIP v3 19/31] cache-tree: introduce write_index_as_tree() Paul Tan
2015-06-18 11:25 ` [PATCH/WIP v3 20/31] am: implement 3-way merge Paul Tan
2015-06-18 11:25 ` [PATCH/WIP v3 21/31] am: --rebasing Paul Tan
2015-06-18 11:25 ` [PATCH/WIP v3 22/31] am: don't use git-mailinfo if --rebasing Paul Tan
2015-06-18 11:25 ` [PATCH/WIP v3 23/31] am: handle stray state directory Paul Tan
2015-06-18 11:25 ` [PATCH/WIP v3 24/31] am: implement -k/--keep, --keep-non-patch Paul Tan
2015-06-18 11:25 ` [PATCH/WIP v3 25/31] am: implement --[no-]message-id, am.messageid Paul Tan
2015-06-18 11:25 ` [PATCH/WIP v3 26/31] am: support --keep-cr, am.keepcr Paul Tan
2015-06-18 11:25 ` [PATCH/WIP v3 27/31] am: implement --[no-]scissors Paul Tan
2015-06-18 11:25 ` [PATCH/WIP v3 28/31] am: pass git-apply's options to git-apply Paul Tan
2015-06-18 11:25 ` [PATCH/WIP v3 29/31] am: implement --ignore-date Paul Tan
2015-06-18 11:25 ` [PATCH/WIP v3 30/31] am: implement --committer-date-is-author-date Paul Tan
2015-06-18 11:25 ` [PATCH/WIP v3 31/31] am: implement -S/--gpg-sign, commit.gpgsign Paul Tan

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

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

  git send-email \
    --in-reply-to='CACRoPnSZn=8keW3meUvLY-B_4vQigMTQW_VVvY2rU8ctjcxcaQ@mail.gmail.com' \
    --to=pyokagan@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=johannes.schindelin@gmx.de \
    --cc=sbeller@google.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.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.