Web lists-archives.com

[PATCH 3/4] trailer: create a new function to handle adding trailers




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@xxxxxxxxxx>
---
 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