@@ -387,8 +387,24 @@ struct merge_options_internal {
387
387
388
388
/* call_depth: recursion level counter for merging merge bases */
389
389
int call_depth ;
390
+
391
+ /* field that holds submodule conflict information */
392
+ struct string_list conflicted_submodules ;
393
+ };
394
+
395
+ struct conflicted_submodule_item {
396
+ char * abbrev ;
397
+ int flag ;
390
398
};
391
399
400
+ static void conflicted_submodule_item_free (void * util , const char * str )
401
+ {
402
+ struct conflicted_submodule_item * item = util ;
403
+
404
+ free (item -> abbrev );
405
+ free (item );
406
+ }
407
+
392
408
struct version_info {
393
409
struct object_id oid ;
394
410
unsigned short mode ;
@@ -517,6 +533,7 @@ enum conflict_and_info_types {
517
533
CONFLICT_SUBMODULE_NOT_INITIALIZED ,
518
534
CONFLICT_SUBMODULE_HISTORY_NOT_AVAILABLE ,
519
535
CONFLICT_SUBMODULE_MAY_HAVE_REWINDS ,
536
+ CONFLICT_SUBMODULE_NULL_MERGE_BASE ,
520
537
521
538
/* Keep this entry _last_ in the list */
522
539
NB_CONFLICT_TYPES ,
@@ -570,6 +587,8 @@ static const char *type_short_descriptions[] = {
570
587
"CONFLICT (submodule history not available)" ,
571
588
[CONFLICT_SUBMODULE_MAY_HAVE_REWINDS ] =
572
589
"CONFLICT (submodule may have rewinds)" ,
590
+ [CONFLICT_SUBMODULE_NULL_MERGE_BASE ] =
591
+ "CONFLICT (submodule lacks merge base)"
573
592
};
574
593
575
594
struct logical_conflict_info {
@@ -686,6 +705,9 @@ static void clear_or_reinit_internal_opts(struct merge_options_internal *opti,
686
705
687
706
mem_pool_discard (& opti -> pool , 0 );
688
707
708
+ string_list_clear_func (& opti -> conflicted_submodules ,
709
+ conflicted_submodule_item_free );
710
+
689
711
/* Clean out callback_data as well. */
690
712
FREE_AND_NULL (renames -> callback_data );
691
713
renames -> callback_data_nr = renames -> callback_data_alloc = 0 ;
@@ -1744,24 +1766,32 @@ static int merge_submodule(struct merge_options *opt,
1744
1766
1745
1767
int i ;
1746
1768
int search = !opt -> priv -> call_depth ;
1769
+ int sub_not_initialized = 1 ;
1770
+ int sub_flag = -1 ;
1747
1771
1748
1772
/* store fallback answer in result in case we fail */
1749
1773
oidcpy (result , opt -> priv -> call_depth ? o : a );
1750
1774
1751
1775
/* we can not handle deletion conflicts */
1752
- if (is_null_oid (o ))
1753
- return 0 ;
1754
- if (is_null_oid (a ))
1755
- return 0 ;
1756
- if (is_null_oid (b ))
1757
- return 0 ;
1776
+ if (is_null_oid (a ) || is_null_oid (b ))
1777
+ BUG ("submodule deleted on one side; this should be handled outside of merge_submodule()" );
1758
1778
1759
- if (repo_submodule_init (& subrepo , opt -> repo , path , null_oid ())) {
1779
+ if ((sub_not_initialized = repo_submodule_init (& subrepo ,
1780
+ opt -> repo , path , null_oid ()))) {
1760
1781
path_msg (opt , CONFLICT_SUBMODULE_NOT_INITIALIZED , 0 ,
1761
1782
path , NULL , NULL , NULL ,
1762
1783
_ ("Failed to merge submodule %s (not checked out)" ),
1763
1784
path );
1764
- return 0 ;
1785
+ sub_flag = CONFLICT_SUBMODULE_NOT_INITIALIZED ;
1786
+ goto cleanup ;
1787
+ }
1788
+
1789
+ if (is_null_oid (o )) {
1790
+ path_msg (opt , CONFLICT_SUBMODULE_NULL_MERGE_BASE , 0 ,
1791
+ path , NULL , NULL , NULL ,
1792
+ _ ("Failed to merge submodule %s (no merge base)" ),
1793
+ path );
1794
+ goto cleanup ;
1765
1795
}
1766
1796
1767
1797
if (!(commit_o = lookup_commit_reference (& subrepo , o )) ||
@@ -1771,6 +1801,7 @@ static int merge_submodule(struct merge_options *opt,
1771
1801
path , NULL , NULL , NULL ,
1772
1802
_ ("Failed to merge submodule %s (commits not present)" ),
1773
1803
path );
1804
+ sub_flag = CONFLICT_SUBMODULE_HISTORY_NOT_AVAILABLE ;
1774
1805
goto cleanup ;
1775
1806
}
1776
1807
@@ -1849,7 +1880,23 @@ static int merge_submodule(struct merge_options *opt,
1849
1880
1850
1881
object_array_clear (& merges );
1851
1882
cleanup :
1852
- repo_clear (& subrepo );
1883
+ if (!opt -> priv -> call_depth && !ret ) {
1884
+ struct string_list * csub = & opt -> priv -> conflicted_submodules ;
1885
+ struct conflicted_submodule_item * util ;
1886
+ const char * abbrev ;
1887
+
1888
+ util = xmalloc (sizeof (* util ));
1889
+ util -> flag = sub_flag ;
1890
+ util -> abbrev = NULL ;
1891
+ if (!sub_not_initialized ) {
1892
+ abbrev = repo_find_unique_abbrev (& subrepo , b , DEFAULT_ABBREV );
1893
+ util -> abbrev = xstrdup (abbrev );
1894
+ }
1895
+ string_list_append (csub , path )-> util = util ;
1896
+ }
1897
+
1898
+ if (!sub_not_initialized )
1899
+ repo_clear (& subrepo );
1853
1900
return ret ;
1854
1901
}
1855
1902
@@ -4434,6 +4481,99 @@ static int record_conflicted_index_entries(struct merge_options *opt)
4434
4481
return errs ;
4435
4482
}
4436
4483
4484
+ static void format_submodule_conflict_suggestion (struct strbuf * msg ) {
4485
+ struct strbuf tmp = STRBUF_INIT ;
4486
+ struct string_list msg_list = STRING_LIST_INIT_DUP ;
4487
+ int i ;
4488
+
4489
+ string_list_split (& msg_list , msg -> buf , '\n' , -1 );
4490
+ for (i = 0 ; i < msg_list .nr ; i ++ ) {
4491
+ if (!i )
4492
+ /*
4493
+ * TRANSLATORS: This is line item of submodule conflict message
4494
+ * from print_submodule_conflict_suggestion() below. For RTL
4495
+ * languages, the following swap is suggested:
4496
+ * " - %s\n" -> "%s - \n"
4497
+ */
4498
+ strbuf_addf (& tmp , _ (" - %s\n" ), msg_list .items [i ].string );
4499
+ else
4500
+ /*
4501
+ * TRANSLATORS: This is line item of submodule conflict message
4502
+ * from print_submodule_conflict_suggestion() below. For RTL
4503
+ * languages, the following swap is suggested:
4504
+ * " %s\n" -> "%s \n"
4505
+ */
4506
+ strbuf_addf (& tmp , _ (" %s\n" ), msg_list .items [i ].string );
4507
+ }
4508
+ strbuf_reset (msg );
4509
+ strbuf_add (msg , tmp .buf , tmp .len );
4510
+ }
4511
+
4512
+ static void print_submodule_conflict_suggestion (struct string_list * csub ) {
4513
+ struct string_list_item * item ;
4514
+ struct strbuf msg = STRBUF_INIT ;
4515
+ struct strbuf tmp = STRBUF_INIT ;
4516
+ struct strbuf subs = STRBUF_INIT ;
4517
+
4518
+ if (!csub -> nr )
4519
+ return ;
4520
+
4521
+ /*
4522
+ * NEEDSWORK: The steps to resolve these errors deserve a more
4523
+ * detailed explanation than what is currently printed below.
4524
+ */
4525
+ for_each_string_list_item (item , csub ) {
4526
+ struct conflicted_submodule_item * util = item -> util ;
4527
+
4528
+ if (util -> flag == CONFLICT_SUBMODULE_NOT_INITIALIZED ||
4529
+ util -> flag == CONFLICT_SUBMODULE_HISTORY_NOT_AVAILABLE )
4530
+ return ;
4531
+ }
4532
+
4533
+ printf (_ ("Recursive merging with submodules currently only supports "
4534
+ "trivial cases.\nPlease manually handle the merging of each "
4535
+ "conflicted submodule.\nThis can be accomplished with the following "
4536
+ "steps:" ));
4537
+ putchar ('\n' );
4538
+
4539
+ for_each_string_list_item (item , csub ) {
4540
+ struct conflicted_submodule_item * util = item -> util ;
4541
+ /*
4542
+ * TRANSLATORS: This is a line of advice to resolve a merge conflict
4543
+ * in a submodule. The second argument is the abbreviated id of the
4544
+ * commit that needs to be merged.
4545
+ * E.g. - go to submodule (sub), and either merge commit abc1234"
4546
+ */
4547
+ strbuf_addf (& tmp , _ ("go to submodule (%s), and either merge commit %s\n"
4548
+ "or update to an existing commit which has merged those changes" ),
4549
+ item -> string , util -> abbrev );
4550
+ format_submodule_conflict_suggestion (& tmp );
4551
+ strbuf_add (& msg , tmp .buf , tmp .len );
4552
+ strbuf_reset (& tmp );
4553
+ }
4554
+ strbuf_add_separated_string_list (& subs , " " , csub );
4555
+ strbuf_addstr (& tmp , _ ("come back to superproject and run:" ));
4556
+ strbuf_addf (& tmp , "\n\ngit add %s\n\n" , subs .buf );
4557
+ strbuf_addstr (& tmp , _ ("to record the above merge or update" ));
4558
+ format_submodule_conflict_suggestion (& tmp );
4559
+ strbuf_add (& msg , tmp .buf , tmp .len );
4560
+ strbuf_reset (& tmp );
4561
+
4562
+ strbuf_addstr (& tmp , _ ("resolve any other conflicts in the superproject" ));
4563
+ format_submodule_conflict_suggestion (& tmp );
4564
+ strbuf_add (& msg , tmp .buf , tmp .len );
4565
+ strbuf_reset (& tmp );
4566
+
4567
+ strbuf_addstr (& tmp , _ ("commit the resulting index in the superproject" ));
4568
+ format_submodule_conflict_suggestion (& tmp );
4569
+ strbuf_add (& msg , tmp .buf , tmp .len );
4570
+
4571
+ printf ("%s" , msg .buf );
4572
+ strbuf_release (& subs );
4573
+ strbuf_release (& tmp );
4574
+ strbuf_release (& msg );
4575
+ }
4576
+
4437
4577
void merge_display_update_messages (struct merge_options * opt ,
4438
4578
int detailed ,
4439
4579
struct merge_result * result )
@@ -4483,6 +4623,8 @@ void merge_display_update_messages(struct merge_options *opt,
4483
4623
}
4484
4624
string_list_clear (& olist , 0 );
4485
4625
4626
+ print_submodule_conflict_suggestion (& opti -> conflicted_submodules );
4627
+
4486
4628
/* Also include needed rename limit adjustment now */
4487
4629
diff_warn_rename_limit ("merge.renamelimit" ,
4488
4630
opti -> renames .needed_limit , 0 );
@@ -4679,6 +4821,7 @@ static void merge_start(struct merge_options *opt, struct merge_result *result)
4679
4821
trace2_region_enter ("merge" , "allocate/init" , opt -> repo );
4680
4822
if (opt -> priv ) {
4681
4823
clear_or_reinit_internal_opts (opt -> priv , 1 );
4824
+ string_list_init_nodup (& opt -> priv -> conflicted_submodules );
4682
4825
trace2_region_leave ("merge" , "allocate/init" , opt -> repo );
4683
4826
return ;
4684
4827
}
0 commit comments