@@ -55,14 +55,56 @@ static void init_src_data(struct src_data *data)
5555static struct string_list srcs = STRING_LIST_INIT_DUP ;
5656static struct string_list origins = STRING_LIST_INIT_DUP ;
5757
58- static int handle_line (char * line )
58+ struct merge_parents {
59+ int alloc , nr ;
60+ struct merge_parent {
61+ unsigned char given [20 ];
62+ unsigned char commit [20 ];
63+ unsigned char used ;
64+ } * item ;
65+ };
66+
67+ /*
68+ * I know, I know, this is inefficient, but you won't be pulling and merging
69+ * hundreds of heads at a time anyway.
70+ */
71+ static struct merge_parent * find_merge_parent (struct merge_parents * table ,
72+ unsigned char * given ,
73+ unsigned char * commit )
74+ {
75+ int i ;
76+ for (i = 0 ; i < table -> nr ; i ++ ) {
77+ if (given && hashcmp (table -> item [i ].given , given ))
78+ continue ;
79+ if (commit && hashcmp (table -> item [i ].commit , commit ))
80+ continue ;
81+ return & table -> item [i ];
82+ }
83+ return NULL ;
84+ }
85+
86+ static void add_merge_parent (struct merge_parents * table ,
87+ unsigned char * given ,
88+ unsigned char * commit )
89+ {
90+ if (table -> nr && find_merge_parent (table , given , commit ))
91+ return ;
92+ ALLOC_GROW (table -> item , table -> nr + 1 , table -> alloc );
93+ hashcpy (table -> item [table -> nr ].given , given );
94+ hashcpy (table -> item [table -> nr ].commit , commit );
95+ table -> item [table -> nr ].used = 0 ;
96+ table -> nr ++ ;
97+ }
98+
99+ static int handle_line (char * line , struct merge_parents * merge_parents )
59100{
60101 int i , len = strlen (line );
61102 struct origin_data * origin_data ;
62103 char * src , * origin ;
63104 struct src_data * src_data ;
64105 struct string_list_item * item ;
65106 int pulling_head = 0 ;
107+ unsigned char sha1 [20 ];
66108
67109 if (len < 43 || line [40 ] != '\t' )
68110 return 1 ;
@@ -73,14 +115,15 @@ static int handle_line(char *line)
73115 if (line [41 ] != '\t' )
74116 return 2 ;
75117
76- line [40 ] = 0 ;
77- origin_data = xcalloc (1 , sizeof (struct origin_data ));
78- i = get_sha1 (line , origin_data -> sha1 );
79- line [40 ] = '\t' ;
80- if (i ) {
81- free (origin_data );
118+ i = get_sha1_hex (line , sha1 );
119+ if (i )
82120 return 3 ;
83- }
121+
122+ if (!find_merge_parent (merge_parents , sha1 , NULL ))
123+ return 0 ; /* subsumed by other parents */
124+
125+ origin_data = xcalloc (1 , sizeof (struct origin_data ));
126+ hashcpy (origin_data -> sha1 , sha1 );
84127
85128 if (line [len - 1 ] == '\n' )
86129 line [len - 1 ] = 0 ;
@@ -472,13 +515,77 @@ static void fmt_merge_msg_sigs(struct strbuf *out)
472515 strbuf_release (& tagbuf );
473516}
474517
518+ static void find_merge_parents (struct merge_parents * result ,
519+ struct strbuf * in , unsigned char * head )
520+ {
521+ struct commit_list * parents , * next ;
522+ struct commit * head_commit ;
523+ int pos = 0 , i , j ;
524+
525+ parents = NULL ;
526+ while (pos < in -> len ) {
527+ int len ;
528+ char * p = in -> buf + pos ;
529+ char * newline = strchr (p , '\n' );
530+ unsigned char sha1 [20 ];
531+ struct commit * parent ;
532+ struct object * obj ;
533+
534+ len = newline ? newline - p : strlen (p );
535+ pos += len + !!newline ;
536+
537+ if (len < 43 ||
538+ get_sha1_hex (p , sha1 ) ||
539+ p [40 ] != '\t' ||
540+ p [41 ] != '\t' )
541+ continue ; /* skip not-for-merge */
542+ /*
543+ * Do not use get_merge_parent() here; we do not have
544+ * "name" here and we do not want to contaminate its
545+ * util field yet.
546+ */
547+ obj = parse_object (sha1 );
548+ parent = (struct commit * )peel_to_type (NULL , 0 , obj , OBJ_COMMIT );
549+ if (!parent )
550+ continue ;
551+ commit_list_insert (parent , & parents );
552+ add_merge_parent (result , obj -> sha1 , parent -> object .sha1 );
553+ }
554+ head_commit = lookup_commit (head );
555+ if (head_commit )
556+ commit_list_insert (head_commit , & parents );
557+ parents = reduce_heads (parents );
558+
559+ while (parents ) {
560+ for (i = 0 ; i < result -> nr ; i ++ )
561+ if (!hashcmp (result -> item [i ].commit ,
562+ parents -> item -> object .sha1 ))
563+ result -> item [i ].used = 1 ;
564+ next = parents -> next ;
565+ free (parents );
566+ parents = next ;
567+ }
568+
569+ for (i = j = 0 ; i < result -> nr ; i ++ ) {
570+ if (result -> item [i ].used ) {
571+ if (i != j )
572+ result -> item [j ] = result -> item [i ];
573+ j ++ ;
574+ }
575+ }
576+ result -> nr = j ;
577+ }
578+
475579int fmt_merge_msg (struct strbuf * in , struct strbuf * out ,
476580 struct fmt_merge_msg_opts * opts )
477581{
478582 int i = 0 , pos = 0 ;
479583 unsigned char head_sha1 [20 ];
480584 const char * current_branch ;
481585 void * current_branch_to_free ;
586+ struct merge_parents merge_parents ;
587+
588+ memset (& merge_parents , 0 , sizeof (merge_parents ));
482589
483590 /* get current branch */
484591 current_branch = current_branch_to_free =
@@ -488,6 +595,8 @@ int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
488595 if (!prefixcmp (current_branch , "refs/heads/" ))
489596 current_branch += 11 ;
490597
598+ find_merge_parents (& merge_parents , in , head_sha1 );
599+
491600 /* get a line */
492601 while (pos < in -> len ) {
493602 int len ;
@@ -498,7 +607,7 @@ int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
498607 pos += len + !!newline ;
499608 i ++ ;
500609 p [len ] = 0 ;
501- if (handle_line (p ))
610+ if (handle_line (p , & merge_parents ))
502611 die ("Error in line %d: %.*s" , i , len , p );
503612 }
504613
@@ -529,6 +638,7 @@ int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
529638
530639 strbuf_complete_line (out );
531640 free (current_branch_to_free );
641+ free (merge_parents .item );
532642 return 0 ;
533643}
534644
0 commit comments