@@ -53,14 +53,56 @@ static void init_src_data(struct src_data *data)
5353static struct string_list srcs = STRING_LIST_INIT_DUP ;
5454static struct string_list origins = STRING_LIST_INIT_DUP ;
5555
56- static int handle_line (char * line )
56+ struct merge_parents {
57+ int alloc , nr ;
58+ struct merge_parent {
59+ unsigned char given [20 ];
60+ unsigned char commit [20 ];
61+ unsigned char used ;
62+ } * item ;
63+ };
64+
65+ /*
66+ * I know, I know, this is inefficient, but you won't be pulling and merging
67+ * hundreds of heads at a time anyway.
68+ */
69+ static struct merge_parent * find_merge_parent (struct merge_parents * table ,
70+ unsigned char * given ,
71+ unsigned char * commit )
72+ {
73+ int i ;
74+ for (i = 0 ; i < table -> nr ; i ++ ) {
75+ if (given && hashcmp (table -> item [i ].given , given ))
76+ continue ;
77+ if (commit && hashcmp (table -> item [i ].commit , commit ))
78+ continue ;
79+ return & table -> item [i ];
80+ }
81+ return NULL ;
82+ }
83+
84+ static void add_merge_parent (struct merge_parents * table ,
85+ unsigned char * given ,
86+ unsigned char * commit )
87+ {
88+ if (table -> nr && find_merge_parent (table , given , commit ))
89+ return ;
90+ ALLOC_GROW (table -> item , table -> nr + 1 , table -> alloc );
91+ hashcpy (table -> item [table -> nr ].given , given );
92+ hashcpy (table -> item [table -> nr ].commit , commit );
93+ table -> item [table -> nr ].used = 0 ;
94+ table -> nr ++ ;
95+ }
96+
97+ static int handle_line (char * line , struct merge_parents * merge_parents )
5798{
5899 int i , len = strlen (line );
59100 struct origin_data * origin_data ;
60101 char * src , * origin ;
61102 struct src_data * src_data ;
62103 struct string_list_item * item ;
63104 int pulling_head = 0 ;
105+ unsigned char sha1 [20 ];
64106
65107 if (len < 43 || line [40 ] != '\t' )
66108 return 1 ;
@@ -71,14 +113,15 @@ static int handle_line(char *line)
71113 if (line [41 ] != '\t' )
72114 return 2 ;
73115
74- line [40 ] = 0 ;
75- origin_data = xcalloc (1 , sizeof (struct origin_data ));
76- i = get_sha1 (line , origin_data -> sha1 );
77- line [40 ] = '\t' ;
78- if (i ) {
79- free (origin_data );
116+ i = get_sha1_hex (line , sha1 );
117+ if (i )
80118 return 3 ;
81- }
119+
120+ if (!find_merge_parent (merge_parents , sha1 , NULL ))
121+ return 0 ; /* subsumed by other parents */
122+
123+ origin_data = xcalloc (1 , sizeof (struct origin_data ));
124+ hashcpy (origin_data -> sha1 , sha1 );
82125
83126 if (line [len - 1 ] == '\n' )
84127 line [len - 1 ] = 0 ;
@@ -366,13 +409,77 @@ static void fmt_merge_msg_sigs(struct strbuf *out)
366409 strbuf_release (& tagbuf );
367410}
368411
412+ static void find_merge_parents (struct merge_parents * result ,
413+ struct strbuf * in , unsigned char * head )
414+ {
415+ struct commit_list * parents , * next ;
416+ struct commit * head_commit ;
417+ int pos = 0 , i , j ;
418+
419+ parents = NULL ;
420+ while (pos < in -> len ) {
421+ int len ;
422+ char * p = in -> buf + pos ;
423+ char * newline = strchr (p , '\n' );
424+ unsigned char sha1 [20 ];
425+ struct commit * parent ;
426+ struct object * obj ;
427+
428+ len = newline ? newline - p : strlen (p );
429+ pos += len + !!newline ;
430+
431+ if (len < 43 ||
432+ get_sha1_hex (p , sha1 ) ||
433+ p [40 ] != '\t' ||
434+ p [41 ] != '\t' )
435+ continue ; /* skip not-for-merge */
436+ /*
437+ * Do not use get_merge_parent() here; we do not have
438+ * "name" here and we do not want to contaminate its
439+ * util field yet.
440+ */
441+ obj = parse_object (sha1 );
442+ parent = (struct commit * )peel_to_type (NULL , 0 , obj , OBJ_COMMIT );
443+ if (!parent )
444+ continue ;
445+ commit_list_insert (parent , & parents );
446+ add_merge_parent (result , obj -> sha1 , parent -> object .sha1 );
447+ }
448+ head_commit = lookup_commit (head );
449+ if (head_commit )
450+ commit_list_insert (head_commit , & parents );
451+ parents = reduce_heads (parents );
452+
453+ while (parents ) {
454+ for (i = 0 ; i < result -> nr ; i ++ )
455+ if (!hashcmp (result -> item [i ].commit ,
456+ parents -> item -> object .sha1 ))
457+ result -> item [i ].used = 1 ;
458+ next = parents -> next ;
459+ free (parents );
460+ parents = next ;
461+ }
462+
463+ for (i = j = 0 ; i < result -> nr ; i ++ ) {
464+ if (result -> item [i ].used ) {
465+ if (i != j )
466+ result -> item [j ] = result -> item [i ];
467+ j ++ ;
468+ }
469+ }
470+ result -> nr = j ;
471+ }
472+
369473int fmt_merge_msg (struct strbuf * in , struct strbuf * out ,
370474 struct fmt_merge_msg_opts * opts )
371475{
372476 int i = 0 , pos = 0 ;
373477 unsigned char head_sha1 [20 ];
374478 const char * current_branch ;
375479 void * current_branch_to_free ;
480+ struct merge_parents merge_parents ;
481+
482+ memset (& merge_parents , 0 , sizeof (merge_parents ));
376483
377484 /* get current branch */
378485 current_branch = current_branch_to_free =
@@ -382,6 +489,8 @@ int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
382489 if (!prefixcmp (current_branch , "refs/heads/" ))
383490 current_branch += 11 ;
384491
492+ find_merge_parents (& merge_parents , in , head_sha1 );
493+
385494 /* get a line */
386495 while (pos < in -> len ) {
387496 int len ;
@@ -392,7 +501,7 @@ int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
392501 pos += len + !!newline ;
393502 i ++ ;
394503 p [len ] = 0 ;
395- if (handle_line (p ))
504+ if (handle_line (p , & merge_parents ))
396505 die ("Error in line %d: %.*s" , i , len , p );
397506 }
398507
@@ -423,6 +532,7 @@ int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
423532
424533 strbuf_complete_line (out );
425534 free (current_branch_to_free );
535+ free (merge_parents .item );
426536 return 0 ;
427537}
428538
0 commit comments