Fossil SCM

Improvements to the "fossil merge" algorithm so that it works better in complex cases involving branch merges where a file was created on one branch but not the other and had its name changed somewhere along the line. See [forum:/forumpost/549700437b|forum post 549700437b] for discussion.

drh 2021-04-16 18:37 trunk
Commit cb4f38ee6733dccc54bcbed81cbb98fb20d577de8323bb2f52f11b377a06fbdf
1 file changed +40 -2
+40 -2
--- src/merge.c
+++ src/merge.c
@@ -135,12 +135,12 @@
135135
** Add an entry to the FV table for all files renamed between
136136
** version N and the version specified by vid.
137137
*/
138138
static void add_renames(
139139
const char *zFnCol, /* The FV column for the filename in vid */
140
- int vid, /* The desired version's RID */
141
- int nid, /* Version N's RID */
140
+ int vid, /* The desired version's checkin RID */
141
+ int nid, /* The checkin rid for the name pivot */
142142
int revOK, /* OK to move backwards (child->parent) if true */
143143
const char *zDebug /* Generate trace output if not NULL */
144144
){
145145
int nChng; /* Number of file name changes */
146146
int *aChng; /* An array of file name changes */
@@ -598,10 +598,48 @@
598598
** Compute name changes from N to V, P, and M
599599
*/
600600
add_renames("fn", vid, nid, 0, debugFlag ? "N->V" : 0);
601601
add_renames("fnp", pid, nid, 0, debugFlag ? "N->P" : 0);
602602
add_renames("fnm", mid, nid, backoutFlag, debugFlag ? "N->M" : 0);
603
+ if( nid!=pid ){
604
+ /* See forum thread https://fossil-scm.org/forum/forumpost/549700437b
605
+ **
606
+ ** If a filename changes between nid and one of the other check-ins
607
+ ** pid, vid, or mid, then it might not have changed for all of them.
608
+ ** try to fill in the appropriate filename in all slots where the
609
+ ** name is missing.
610
+ **
611
+ ** This does not work if
612
+ ** (1) The filename changes more than once in between nid and vid/mid
613
+ ** (2) Two or more filenames swap places - for example if A is renamed
614
+ ** to B and B is renamed to A.
615
+ ** The Fossil merge algorithm breaks down in those cases. It will need
616
+ ** to be completely rewritten to handle such complex cases. Such cases
617
+ ** appear to be rare, and also confusing to humans.
618
+ */
619
+ db_multi_exec(
620
+ "UPDATE fv SET fn=vfile.pathname FROM vfile"
621
+ " WHERE fn IS NULL"
622
+ " AND vfile.pathname IN (fv.fnm,fv.fnp,fv.fnn)"
623
+ " AND vfile.vid=%d;",
624
+ vid
625
+ );
626
+ db_multi_exec(
627
+ "UPDATE fv SET fnp=vfile.pathname FROM vfile"
628
+ " WHERE fnp IS NULL"
629
+ " AND vfile.pathname IN (fv.fn,fv.fnm,fv.fnn)"
630
+ " AND vfile.vid=%d;",
631
+ pid
632
+ );
633
+ db_multi_exec(
634
+ "UPDATE fv SET fnm=vfile.pathname FROM vfile"
635
+ " WHERE fnm IS NULL"
636
+ " AND vfile.pathname IN (fv.fn,fv.fnp,fv.fnn)"
637
+ " AND vfile.vid=%d;",
638
+ mid
639
+ );
640
+ }
603641
if( debugFlag ){
604642
fossil_print("******** FV after name change search *******\n");
605643
debug_fv_dump(1);
606644
}
607645
608646
--- src/merge.c
+++ src/merge.c
@@ -135,12 +135,12 @@
135 ** Add an entry to the FV table for all files renamed between
136 ** version N and the version specified by vid.
137 */
138 static void add_renames(
139 const char *zFnCol, /* The FV column for the filename in vid */
140 int vid, /* The desired version's RID */
141 int nid, /* Version N's RID */
142 int revOK, /* OK to move backwards (child->parent) if true */
143 const char *zDebug /* Generate trace output if not NULL */
144 ){
145 int nChng; /* Number of file name changes */
146 int *aChng; /* An array of file name changes */
@@ -598,10 +598,48 @@
598 ** Compute name changes from N to V, P, and M
599 */
600 add_renames("fn", vid, nid, 0, debugFlag ? "N->V" : 0);
601 add_renames("fnp", pid, nid, 0, debugFlag ? "N->P" : 0);
602 add_renames("fnm", mid, nid, backoutFlag, debugFlag ? "N->M" : 0);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
603 if( debugFlag ){
604 fossil_print("******** FV after name change search *******\n");
605 debug_fv_dump(1);
606 }
607
608
--- src/merge.c
+++ src/merge.c
@@ -135,12 +135,12 @@
135 ** Add an entry to the FV table for all files renamed between
136 ** version N and the version specified by vid.
137 */
138 static void add_renames(
139 const char *zFnCol, /* The FV column for the filename in vid */
140 int vid, /* The desired version's checkin RID */
141 int nid, /* The checkin rid for the name pivot */
142 int revOK, /* OK to move backwards (child->parent) if true */
143 const char *zDebug /* Generate trace output if not NULL */
144 ){
145 int nChng; /* Number of file name changes */
146 int *aChng; /* An array of file name changes */
@@ -598,10 +598,48 @@
598 ** Compute name changes from N to V, P, and M
599 */
600 add_renames("fn", vid, nid, 0, debugFlag ? "N->V" : 0);
601 add_renames("fnp", pid, nid, 0, debugFlag ? "N->P" : 0);
602 add_renames("fnm", mid, nid, backoutFlag, debugFlag ? "N->M" : 0);
603 if( nid!=pid ){
604 /* See forum thread https://fossil-scm.org/forum/forumpost/549700437b
605 **
606 ** If a filename changes between nid and one of the other check-ins
607 ** pid, vid, or mid, then it might not have changed for all of them.
608 ** try to fill in the appropriate filename in all slots where the
609 ** name is missing.
610 **
611 ** This does not work if
612 ** (1) The filename changes more than once in between nid and vid/mid
613 ** (2) Two or more filenames swap places - for example if A is renamed
614 ** to B and B is renamed to A.
615 ** The Fossil merge algorithm breaks down in those cases. It will need
616 ** to be completely rewritten to handle such complex cases. Such cases
617 ** appear to be rare, and also confusing to humans.
618 */
619 db_multi_exec(
620 "UPDATE fv SET fn=vfile.pathname FROM vfile"
621 " WHERE fn IS NULL"
622 " AND vfile.pathname IN (fv.fnm,fv.fnp,fv.fnn)"
623 " AND vfile.vid=%d;",
624 vid
625 );
626 db_multi_exec(
627 "UPDATE fv SET fnp=vfile.pathname FROM vfile"
628 " WHERE fnp IS NULL"
629 " AND vfile.pathname IN (fv.fn,fv.fnm,fv.fnn)"
630 " AND vfile.vid=%d;",
631 pid
632 );
633 db_multi_exec(
634 "UPDATE fv SET fnm=vfile.pathname FROM vfile"
635 " WHERE fnm IS NULL"
636 " AND vfile.pathname IN (fv.fn,fv.fnp,fv.fnn)"
637 " AND vfile.vid=%d;",
638 mid
639 );
640 }
641 if( debugFlag ){
642 fossil_print("******** FV after name change search *******\n");
643 debug_fv_dump(1);
644 }
645
646

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button