From: Paolo Bonzini <pbonzini@redhat.com>
To: git@vger.kernel.org
Subject: [PATCH 3/4] trailer: create a new function to handle adding trailers
Date: Thu, 5 Oct 2017 15:22:42 +0200 [thread overview]
Message-ID: <20171005132243.27058-4-pbonzini@redhat.com> (raw)
In-Reply-To: <20171005132243.27058-1-pbonzini@redhat.com>
Create a new function apply_arg that takes care of computing the new
trailer's "neighbor", checking for duplicates through a pluggable
callback, and adding the new argument according to "trailer.where".
Rename after_or_end, and don't use it in apply_arg. It's a coincidence
that the conditions for "scan backwards" and "add after" are the same.
This simplifies find_same_and_apply_arg so that it does exactly what
the name says. apply_arg_if_missing can also use the new function;
before, it was redoing add_arg_to_input_list's job in a slightly
different fashion.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
trailer.c | 125 +++++++++++++++++++++++++++++++++++++-------------------------
1 file changed, 75 insertions(+), 50 deletions(-)
diff --git a/trailer.c b/trailer.c
index 91f89db7f..ce0d94074 100644
--- a/trailer.c
+++ b/trailer.c
@@ -58,7 +58,7 @@ static const char *git_generated_prefixes[] = {
pos != (head); \
pos = is_reverse ? pos->prev : pos->next)
-static int after_or_end(enum trailer_where where)
+static int scan_backwards(enum trailer_where where)
{
return (where == WHERE_AFTER) || (where == WHERE_END);
}
@@ -181,18 +181,8 @@ static struct trailer_item *trailer_from_arg(struct arg_item *arg_tok)
return new;
}
-static void add_arg_to_input_list(struct trailer_item *on_tok,
- struct arg_item *arg_tok)
-{
- int aoe = after_or_end(arg_tok->conf.where);
- struct trailer_item *to_add = trailer_from_arg(arg_tok);
- if (aoe)
- list_add(&to_add->list, &on_tok->list);
- else
- list_add_tail(&to_add->list, &on_tok->list);
-}
-
static int check_if_different(struct trailer_item *in_tok,
+ struct trailer_item *neighbor,
struct arg_item *arg_tok,
struct list_head *head)
{
@@ -203,8 +193,8 @@ static int check_if_different(struct trailer_item *in_tok,
* if we want to add a trailer after another one,
* we have to check those before this one
*/
- next_head = after_or_end(where) ? in_tok->list.prev
- : in_tok->list.next;
+ next_head = scan_backwards(where) ? in_tok->list.prev
+ : in_tok->list.next;
if (next_head == head)
return 1;
in_tok = list_entry(next_head, struct trailer_item, list);
@@ -212,6 +202,14 @@ static int check_if_different(struct trailer_item *in_tok,
return 0;
}
+static int check_if_different_neighbor(struct trailer_item *in_tok,
+ struct trailer_item *neighbor,
+ struct arg_item *arg_tok,
+ struct list_head *head)
+{
+ return !same_trailer(neighbor, arg_tok);
+}
+
static char *apply_command(const char *command, const char *arg)
{
struct strbuf cmd = STRBUF_INIT;
@@ -260,33 +258,80 @@ static void apply_item_command(struct trailer_item *in_tok, struct arg_item *arg
}
}
+static int apply_arg(struct trailer_item *in_tok,
+ struct arg_item *arg_tok,
+ struct list_head *head,
+ int (*check)(struct trailer_item *in_tok,
+ struct trailer_item *neighbor,
+ struct arg_item *arg_tok,
+ struct list_head *head),
+ int replace)
+{
+ struct trailer_item *to_add, *neighbor;
+ struct list_head *place;
+ int add_after;
+
+ enum trailer_where where = arg_tok->conf.where;
+ int middle = (where == WHERE_AFTER) || (where == WHERE_BEFORE);
+
+ /*
+ * No other trailer to apply arg_tok one before/after. Put it
+ * before/after _all_ other trailers.
+ */
+ if (!in_tok && middle) {
+ where = (where == WHERE_AFTER) ? WHERE_END : WHERE_START;
+ middle = 0;
+ }
+
+ if (list_empty(head)) {
+ add_after = 1;
+ place = head;
+ neighbor = NULL;
+ } else if (middle) {
+ add_after = (where == WHERE_AFTER);
+ place = &in_tok->list;
+ neighbor = in_tok;
+ } else {
+ add_after = (where == WHERE_END);
+ place = (where == WHERE_END) ? head->prev : head->next;
+ neighbor = list_entry(place, struct trailer_item, list);
+ }
+
+ apply_item_command(in_tok, arg_tok);
+ if (check && !check(in_tok, neighbor, arg_tok, head))
+ return 0;
+
+ to_add = trailer_from_arg(arg_tok);
+ if (add_after)
+ list_add(&to_add->list, place);
+ else
+ list_add_tail(&to_add->list, place);
+
+ if (replace) {
+ list_del(&in_tok->list);
+ free_trailer_item(in_tok);
+ }
+ return 1;
+}
+
static void apply_arg_if_exists(struct trailer_item *in_tok,
struct arg_item *arg_tok,
- struct trailer_item *on_tok,
struct list_head *head)
{
switch (arg_tok->conf.if_exists) {
case EXISTS_DO_NOTHING:
break;
case EXISTS_REPLACE:
- apply_item_command(in_tok, arg_tok);
- add_arg_to_input_list(on_tok, arg_tok);
- list_del(&in_tok->list);
- free_trailer_item(in_tok);
+ apply_arg(in_tok, arg_tok, head, NULL, 1);
break;
case EXISTS_ADD:
- apply_item_command(in_tok, arg_tok);
- add_arg_to_input_list(on_tok, arg_tok);
+ apply_arg(in_tok, arg_tok, head, NULL, 0);
break;
case EXISTS_ADD_IF_DIFFERENT:
- apply_item_command(in_tok, arg_tok);
- if (check_if_different(in_tok, arg_tok, head))
- add_arg_to_input_list(on_tok, arg_tok);
+ apply_arg(in_tok, arg_tok, head, check_if_different, 0);
break;
case EXISTS_ADD_IF_DIFFERENT_NEIGHBOR:
- apply_item_command(in_tok, arg_tok);
- if (!same_trailer(on_tok, arg_tok))
- add_arg_to_input_list(on_tok, arg_tok);
+ apply_arg(in_tok, arg_tok, head, check_if_different_neighbor, 0);
break;
default:
die("BUG: trailer.c: unhandled value %d",
@@ -297,24 +342,12 @@ static void apply_arg_if_exists(struct trailer_item *in_tok,
static void apply_arg_if_missing(struct list_head *head,
struct arg_item *arg_tok)
{
- enum trailer_where where;
- struct trailer_item *to_add;
-
switch (arg_tok->conf.if_missing) {
case MISSING_DO_NOTHING:
break;
case MISSING_ADD:
- where = arg_tok->conf.where;
- apply_item_command(NULL, arg_tok);
- to_add = trailer_from_arg(arg_tok);
- if (after_or_end(where))
- list_add_tail(&to_add->list, head);
- else
- list_add(&to_add->list, head);
+ apply_arg(NULL, arg_tok, head, NULL, 0);
break;
- default:
- die("BUG: trailer.c: unhandled value %d",
- arg_tok->conf.if_missing);
}
}
@@ -323,26 +356,18 @@ static int find_same_and_apply_arg(struct list_head *head,
{
struct list_head *pos;
struct trailer_item *in_tok;
- struct trailer_item *on_tok;
enum trailer_where where = arg_tok->conf.where;
- int middle = (where == WHERE_AFTER) || (where == WHERE_BEFORE);
- int backwards = after_or_end(where);
- struct trailer_item *start_tok;
+ int backwards = scan_backwards(where);
if (list_empty(head))
return 0;
- start_tok = list_entry(backwards ? head->prev : head->next,
- struct trailer_item,
- list);
-
list_for_each_dir(pos, head, backwards) {
in_tok = list_entry(pos, struct trailer_item, list);
if (!same_token(in_tok, arg_tok))
continue;
- on_tok = middle ? in_tok : start_tok;
- apply_arg_if_exists(in_tok, arg_tok, on_tok, head);
+ apply_arg_if_exists(in_tok, arg_tok, head);
return 1;
}
return 0;
--
2.14.2
next prev parent reply other threads:[~2017-10-05 13:22 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-10-05 13:22 [RFC PATCH 0/4] interpret-trailers: introduce "move" action Paolo Bonzini
2017-10-05 13:22 ` [PATCH 1/4] trailer: push free_arg_item up Paolo Bonzini
2017-10-05 13:22 ` [PATCH 2/4] trailer: simplify check_if_different Paolo Bonzini
2017-10-05 13:22 ` Paolo Bonzini [this message]
2017-10-05 13:22 ` [PATCH 4/4] trailer: add "move" configuration for trailer.ifExists Paolo Bonzini
2017-10-06 6:44 ` [RFC PATCH 0/4] interpret-trailers: introduce "move" action Junio C Hamano
2017-10-06 7:26 ` Paolo Bonzini
2017-10-06 10:30 ` Christian Couder
2017-10-06 10:40 ` Paolo Bonzini
2017-10-06 12:33 ` Christian Couder
2017-10-06 12:39 ` Paolo Bonzini
2017-10-06 13:19 ` Christian Couder
2017-10-06 13:49 ` Paolo Bonzini
2017-10-07 0:51 ` Junio C Hamano
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=20171005132243.27058-4-pbonzini@redhat.com \
--to=pbonzini@redhat.com \
--cc=git@vger.kernel.org \
/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 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 NNTP newsgroup(s).