@@ -55,14 +55,56 @@ static void init_src_data(struct src_data *data)
55
55
static struct string_list srcs = STRING_LIST_INIT_DUP ;
56
56
static struct string_list origins = STRING_LIST_INIT_DUP ;
57
57
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 )
59
100
{
60
101
int i , len = strlen (line );
61
102
struct origin_data * origin_data ;
62
103
char * src , * origin ;
63
104
struct src_data * src_data ;
64
105
struct string_list_item * item ;
65
106
int pulling_head = 0 ;
107
+ unsigned char sha1 [20 ];
66
108
67
109
if (len < 43 || line [40 ] != '\t' )
68
110
return 1 ;
@@ -73,14 +115,15 @@ static int handle_line(char *line)
73
115
if (line [41 ] != '\t' )
74
116
return 2 ;
75
117
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 )
82
120
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 );
84
127
85
128
if (line [len - 1 ] == '\n' )
86
129
line [len - 1 ] = 0 ;
@@ -472,13 +515,77 @@ static void fmt_merge_msg_sigs(struct strbuf *out)
472
515
strbuf_release (& tagbuf );
473
516
}
474
517
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
+
475
579
int fmt_merge_msg (struct strbuf * in , struct strbuf * out ,
476
580
struct fmt_merge_msg_opts * opts )
477
581
{
478
582
int i = 0 , pos = 0 ;
479
583
unsigned char head_sha1 [20 ];
480
584
const char * current_branch ;
481
585
void * current_branch_to_free ;
586
+ struct merge_parents merge_parents ;
587
+
588
+ memset (& merge_parents , 0 , sizeof (merge_parents ));
482
589
483
590
/* get current branch */
484
591
current_branch = current_branch_to_free =
@@ -488,6 +595,8 @@ int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
488
595
if (!prefixcmp (current_branch , "refs/heads/" ))
489
596
current_branch += 11 ;
490
597
598
+ find_merge_parents (& merge_parents , in , head_sha1 );
599
+
491
600
/* get a line */
492
601
while (pos < in -> len ) {
493
602
int len ;
@@ -498,7 +607,7 @@ int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
498
607
pos += len + !!newline ;
499
608
i ++ ;
500
609
p [len ] = 0 ;
501
- if (handle_line (p ))
610
+ if (handle_line (p , & merge_parents ))
502
611
die ("Error in line %d: %.*s" , i , len , p );
503
612
}
504
613
@@ -529,6 +638,7 @@ int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
529
638
530
639
strbuf_complete_line (out );
531
640
free (current_branch_to_free );
641
+ free (merge_parents .item );
532
642
return 0 ;
533
643
}
534
644
0 commit comments