From: Junio C Hamano <gitster@pobox.com>
To: Christian Couder <chriscool@tuxfamily.org>
Cc: git@vger.kernel.org, Johan Herland <johan@herland.net>,
Josh Triplett <josh@joshtriplett.org>,
Thomas Rast <tr@thomasrast.ch>,
Michael Haggerty <mhagger@alum.mit.edu>,
Eric Sunshine <sunshine@sunshineco.com>,
Dan Carpenter <dan.carpenter@oracle.com>,
Greg Kroah-Hartman <greg@kroah.com>, Jeff King <peff@peff.net>
Subject: Re: [PATCH v5 02/14] trailer: process trailers from file and arguments
Date: Thu, 06 Feb 2014 16:03:10 -0800 [thread overview]
Message-ID: <xmqqr47fx001.fsf@gitster.dls.corp.google.com> (raw)
In-Reply-To: <20140206202004.325.96525.chriscool@tuxfamily.org> (Christian Couder's message of "Thu, 06 Feb 2014 21:19:51 +0100")
Christian Couder <chriscool@tuxfamily.org> writes:
> This patch implements the logic that process trailers
> from file and arguments.
>
> At the beginning trailers from file are in their own
> infile_tok doubly linked list, and trailers from
> arguments are in their own arg_tok doubly linked list.
>
> The lists are traversed and when an arg_tok should be
> "applied", it is removed from its list and inserted
> into the infile_tok list.
>
> Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
> ---
> trailer.c | 187 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 187 insertions(+)
>
> diff --git a/trailer.c b/trailer.c
> index f129b5a..ba0cfe0 100644
> --- a/trailer.c
> +++ b/trailer.c
> @@ -46,3 +46,190 @@ static inline size_t alnum_len(const char *buf, int len)
> while (--len >= 0 && !isalnum(buf[len]));
> return (size_t) len + 1;
> }
> +
> +static void add_arg_to_infile(struct trailer_item *infile_tok,
> + struct trailer_item *arg_tok)
> +{
> + if (arg_tok->conf->where == WHERE_AFTER) {
> + arg_tok->next = infile_tok->next;
> + infile_tok->next = arg_tok;
> + arg_tok->previous = infile_tok;
> + if (arg_tok->next)
> + arg_tok->next->previous = arg_tok;
> + } else {
> + arg_tok->previous = infile_tok->previous;
> + infile_tok->previous = arg_tok;
> + arg_tok->next = infile_tok;
> + if (arg_tok->previous)
> + arg_tok->previous->next = arg_tok;
> + }
> +}
> +
> +static int check_if_different(struct trailer_item *infile_tok,
> + struct trailer_item *arg_tok,
> + int alnum_len, int check_all)
> +{
> + enum action_where where = arg_tok->conf->where;
> + do {
> + if (!infile_tok)
> + return 1;
> + if (same_trailer(infile_tok, arg_tok, alnum_len))
> + return 0;
> + /*
> + * if we want to add a trailer after another one,
> + * we have to check those before this one
> + */
> + infile_tok = (where == WHERE_AFTER) ? infile_tok->previous : infile_tok->next;
> + } while (check_all);
> + return 1;
> +}
> +
> +static void apply_arg_if_exist(struct trailer_item *infile_tok,
> + struct trailer_item *arg_tok,
> + int alnum_len)
> +{
> + switch (arg_tok->conf->if_exist) {
> + case EXIST_DO_NOTHING:
> + free(arg_tok);
> + break;
> + case EXIST_OVERWRITE:
> + free((char *)infile_tok->value);
> + infile_tok->value = xstrdup(arg_tok->value);
> + free(arg_tok);
> + break;
> + case EXIST_ADD:
> + add_arg_to_infile(infile_tok, arg_tok);
> + break;
> + case EXIST_ADD_IF_DIFFERENT:
> + if (check_if_different(infile_tok, arg_tok, alnum_len, 1))
> + add_arg_to_infile(infile_tok, arg_tok);
> + else
> + free(arg_tok);
> + break;
> + case EXIST_ADD_IF_DIFFERENT_NEIGHBOR:
> + if (check_if_different(infile_tok, arg_tok, alnum_len, 0))
> + add_arg_to_infile(infile_tok, arg_tok);
> + else
> + free(arg_tok);
> + break;
Makes me wonder if people want a rule to say "if the same key
already exists, regardless of the value".
> + }
> +}
> +
> +static void remove_from_list(struct trailer_item *item,
> + struct trailer_item **first)
> +{
> + if (item->next)
> + item->next->previous = item->previous;
> + if (item->previous)
> + item->previous->next = item->next;
> + else
> + *first = item->next;
> +}
Will callers free the item that now is not on the list?
> +static struct trailer_item *remove_first(struct trailer_item **first)
> +{
> + struct trailer_item *item = *first;
> + *first = item->next;
> + if (item->next) {
> + item->next->previous = NULL;
> + item->next = NULL;
> + }
> + return item;
> +}
> +
> +static void process_infile_tok(struct trailer_item *infile_tok,
> + struct trailer_item **arg_tok_first,
> + enum action_where where)
> +{
> + struct trailer_item *arg_tok;
> + struct trailer_item *next_arg;
> +
> + int tok_alnum_len = alnum_len(infile_tok->token, strlen(infile_tok->token));
> + for (arg_tok = *arg_tok_first; arg_tok; arg_tok = next_arg) {
> + next_arg = arg_tok->next;
> + if (same_token(infile_tok, arg_tok, tok_alnum_len) &&
> + arg_tok->conf->where == where) {
> + remove_from_list(arg_tok, arg_tok_first);
> + apply_arg_if_exist(infile_tok, arg_tok, tok_alnum_len);
> + /*
> + * If arg has been added to infile,
> + * then we need to process it too now.
> + */
> + if ((where == WHERE_AFTER ? infile_tok->next : infile_tok->previous) == arg_tok)
> + infile_tok = arg_tok;
> + }
> + }
> +}
> +
> +static void update_last(struct trailer_item **last)
> +{
> + if (*last)
> + while((*last)->next != NULL)
> + *last = (*last)->next;
> +}
> +
> +static void update_first(struct trailer_item **first)
> +{
> + if (*first)
> + while((*first)->previous != NULL)
> + *first = (*first)->previous;
> +}
> +
> +static void apply_arg_if_missing(struct trailer_item **infile_tok_first,
> + struct trailer_item **infile_tok_last,
> + struct trailer_item *arg_tok)
> +{
Makes me wonder if it would make the code simpler to keep an anchor
item "struct trailer_item" that is off heap, and pass that single
anchor item around, using its next/prev fields as the first and the
last. Wouldn't it let you remove the special cases for the first
and last item?
> + struct trailer_item **infile_tok;
> + enum action_where where;
> +
> + switch (arg_tok->conf->if_missing) {
> + case MISSING_DO_NOTHING:
> + free(arg_tok);
> + break;
> + case MISSING_ADD:
> + where = arg_tok->conf->where;
> + infile_tok = (where == WHERE_AFTER) ? infile_tok_last : infile_tok_first;
> + if (*infile_tok) {
> + add_arg_to_infile(*infile_tok, arg_tok);
> + *infile_tok = arg_tok;
> + } else {
> + *infile_tok_first = arg_tok;
> + *infile_tok_last = arg_tok;
> + }
> + break;
This piece makes me wonder if "after" is a good name. prepend and
append, perhaps?
next prev parent reply other threads:[~2014-02-07 0:03 UTC|newest]
Thread overview: 48+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-02-06 20:19 [PATCH v5 00/14] Add interpret-trailers builtin Christian Couder
2014-02-06 20:19 ` [PATCH v5 01/14] Add data structures and basic functions for commit trailers Christian Couder
2014-02-06 23:44 ` Junio C Hamano
2014-02-09 13:48 ` Christian Couder
2014-02-10 7:27 ` Eric Sunshine
2014-02-06 23:46 ` Junio C Hamano
2014-02-09 13:51 ` Christian Couder
2014-02-06 20:19 ` [PATCH v5 02/14] trailer: process trailers from file and arguments Christian Couder
2014-02-07 0:03 ` Junio C Hamano [this message]
2014-02-09 13:52 ` Christian Couder
2014-02-10 18:14 ` Junio C Hamano
2014-02-10 19:59 ` Christian Couder
2014-02-10 20:51 ` Junio C Hamano
2014-02-11 15:02 ` Christian Couder
2014-02-11 18:07 ` Junio C Hamano
2014-02-14 21:41 ` Christian Couder
2014-02-14 21:46 ` Junio C Hamano
2014-02-14 23:29 ` Christian Couder
2014-02-14 23:39 ` Junio C Hamano
2014-02-14 23:57 ` Junio C Hamano
2014-02-15 0:16 ` Junio C Hamano
2014-02-21 0:22 ` Junio C Hamano
2014-02-23 10:44 ` Christian Couder
2014-02-06 20:19 ` [PATCH v5 03/14] trailer: read and process config information Christian Couder
2014-02-06 20:19 ` [PATCH v5 04/14] trailer: process command line trailer arguments Christian Couder
2014-02-07 0:08 ` Junio C Hamano
2014-02-09 14:06 ` Christian Couder
2014-02-06 20:19 ` [PATCH v5 05/14] trailer: parse trailers from input file Christian Couder
2014-02-06 20:19 ` [PATCH v5 06/14] trailer: put all the processing together and print Christian Couder
2014-02-06 20:19 ` [PATCH v5 07/14] trailer: add interpret-trailers command Christian Couder
2014-02-07 0:10 ` Junio C Hamano
2014-02-07 8:34 ` Christian Couder
2014-02-07 18:09 ` Junio C Hamano
2014-02-07 20:35 ` Junio C Hamano
2014-02-06 20:19 ` [PATCH v5 08/14] trailer: add tests for "git interpret-trailers" Christian Couder
2014-02-07 0:11 ` Junio C Hamano
2014-02-06 20:19 ` [PATCH v5 09/14] trailer: if no input file is passed, read from stdin Christian Couder
2014-02-07 0:12 ` Junio C Hamano
2014-02-06 20:19 ` [PATCH v5 10/14] trailer: execute command from 'trailer.<name>.command' Christian Couder
2014-02-07 0:18 ` Junio C Hamano
2014-02-07 18:17 ` Junio C Hamano
2014-02-06 20:20 ` [PATCH v5 11/14] trailer: add tests for trailer command Christian Couder
2014-02-06 20:20 ` [PATCH v5 12/14] trailer: set author and committer env variables Christian Couder
2014-02-07 0:20 ` Junio C Hamano
2014-02-07 0:26 ` Junio C Hamano
2014-02-06 20:20 ` [PATCH v5 13/14] trailer: add tests for commands using " Christian Couder
2014-02-06 20:20 ` [PATCH v5 14/14] Documentation: add documentation for 'git interpret-trailers' Christian Couder
2014-02-10 7:17 ` Eric Sunshine
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=xmqqr47fx001.fsf@gitster.dls.corp.google.com \
--to=gitster@pobox.com \
--cc=chriscool@tuxfamily.org \
--cc=dan.carpenter@oracle.com \
--cc=git@vger.kernel.org \
--cc=greg@kroah.com \
--cc=johan@herland.net \
--cc=josh@joshtriplett.org \
--cc=mhagger@alum.mit.edu \
--cc=peff@peff.net \
--cc=sunshine@sunshineco.com \
--cc=tr@thomasrast.ch \
/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.