git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
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



  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).