@@ -53,14 +53,56 @@ static void init_src_data(struct src_data *data)
53
53
static struct string_list srcs = STRING_LIST_INIT_DUP ;
54
54
static struct string_list origins = STRING_LIST_INIT_DUP ;
55
55
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 )
57
98
{
58
99
int i , len = strlen (line );
59
100
struct origin_data * origin_data ;
60
101
char * src , * origin ;
61
102
struct src_data * src_data ;
62
103
struct string_list_item * item ;
63
104
int pulling_head = 0 ;
105
+ unsigned char sha1 [20 ];
64
106
65
107
if (len < 43 || line [40 ] != '\t' )
66
108
return 1 ;
@@ -71,14 +113,15 @@ static int handle_line(char *line)
71
113
if (line [41 ] != '\t' )
72
114
return 2 ;
73
115
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 )
80
118
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 );
82
125
83
126
if (line [len - 1 ] == '\n' )
84
127
line [len - 1 ] = 0 ;
@@ -366,13 +409,77 @@ static void fmt_merge_msg_sigs(struct strbuf *out)
366
409
strbuf_release (& tagbuf );
367
410
}
368
411
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
+
369
473
int fmt_merge_msg (struct strbuf * in , struct strbuf * out ,
370
474
struct fmt_merge_msg_opts * opts )
371
475
{
372
476
int i = 0 , pos = 0 ;
373
477
unsigned char head_sha1 [20 ];
374
478
const char * current_branch ;
375
479
void * current_branch_to_free ;
480
+ struct merge_parents merge_parents ;
481
+
482
+ memset (& merge_parents , 0 , sizeof (merge_parents ));
376
483
377
484
/* get current branch */
378
485
current_branch = current_branch_to_free =
@@ -382,6 +489,8 @@ int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
382
489
if (!prefixcmp (current_branch , "refs/heads/" ))
383
490
current_branch += 11 ;
384
491
492
+ find_merge_parents (& merge_parents , in , head_sha1 );
493
+
385
494
/* get a line */
386
495
while (pos < in -> len ) {
387
496
int len ;
@@ -392,7 +501,7 @@ int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
392
501
pos += len + !!newline ;
393
502
i ++ ;
394
503
p [len ] = 0 ;
395
- if (handle_line (p ))
504
+ if (handle_line (p , & merge_parents ))
396
505
die ("Error in line %d: %.*s" , i , len , p );
397
506
}
398
507
@@ -423,6 +532,7 @@ int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
423
532
424
533
strbuf_complete_line (out );
425
534
free (current_branch_to_free );
535
+ free (merge_parents .item );
426
536
return 0 ;
427
537
}
428
538
0 commit comments