Fossil SCM

Add a new "SUGGESTED CONFLICT RESOLUTION" section to the conflict markings.

drh 2024-12-05 17:00 better-merge
Commit adf2269602f11f644f35637f9f1dbf43ba845730b2e9ca6728fccc31eca8eb34
2 files changed +32 -24 +55 -40
+32 -24
--- src/merge.tcl
+++ src/merge.tcl
@@ -122,74 +122,80 @@
122122
set lnC 1
123123
set lnD 1
124124
foreach {A B C D} $mergetxt {
125125
set key1 [string index $A 0]
126126
if {$key1=="S"} {
127
- set N [string range $A 1 end]
128
- incr lnA $N
129
- incr lnB $N
130
- incr lnC $N
131
- incr lnD $N
132
- .lnA insert end ...\n hrln
133
- .txtA insert end [string repeat . 30]\n hrtxt
134
- .lnB insert end ...\n hrln
135
- .txtB insert end [string repeat . 30]\n hrtxt
136
- .lnC insert end ...\n hrln
137
- .txtC insert end [string repeat . 30]\n hrtxt
138
- .lnD insert end ...\n hrln
139
- .txtD insert end [string repeat . 30]\n hrtxt
127
+ scan [string range $A 1 end] "%d %d %d %d" nA nB nC nD
128
+ foreach x {A B C D} {
129
+ set N [set n$x]
130
+ incr ln$x $N
131
+ if {$N>0} {
132
+ .ln$x insert end ...\n hrln
133
+ .txt$x insert end [string repeat . 30]\n hrtxt
134
+ } else {
135
+ .ln$x insert end \n hrln
136
+ .txt$x insert end \n hrtxt
137
+ }
138
+ }
140139
continue
141140
}
142141
set key2 [string index $B 0]
143142
set key3 [string index $C 0]
144143
set key4 [string index $D 0]
145
- if {$key4=="X"} {set dtag rm} {set dtag -}
146144
if {$key1=="."} {
147145
.lnA insert end \n -
148
- .txtA insert end \n $dtag
146
+ .txtA insert end \n -
149147
} elseif {$key1=="N"} {
150148
.nameA config -text [string range $A 1 end]
151149
} else {
152150
.lnA insert end $lnA\n -
153151
incr lnA
154
- .txtA insert end [string range $A 1 end]\n $dtag
152
+ if {$key1=="X"} {
153
+ .txtA insert end [string range $A 1 end]\n rm
154
+ } else {
155
+ .txtA insert end [string range $A 1 end]\n -
156
+ }
155157
}
156158
if {$key2=="."} {
157159
.lnB insert end \n -
158
- .txtB insert end \n $dtag
160
+ .txtB insert end \n -
159161
} elseif {$key2=="N"} {
160162
.nameB config -text [string range $B 1 end]
161163
} else {
162164
.lnB insert end $lnB\n -
163165
incr lnB
164
- if {$key4=="2"} {set tag chng} {set tag $dtag}
166
+ if {$key4=="2"} {set tag chng} {set tag -}
165167
if {$key2=="1"} {
166168
.txtB insert end [string range $A 1 end]\n $tag
169
+ } elseif {$key2=="X"} {
170
+ .txtB insert end [string range $B 1 end]\n rm
167171
} else {
168172
.txtB insert end [string range $B 1 end]\n $tag
169173
}
170174
}
171175
if {$key3=="."} {
172176
.lnC insert end \n -
173
- .txtC insert end \n $dtag
174
- } elseif {$key3=="N"} {
177
+ .txtC insert end \n -
178
+ } elseif {$key3=="N"} {
175179
.nameC config -text [string range $C 1 end]
176180
} else {
177181
.lnC insert end $lnC\n -
178182
incr lnC
179
- if {$key4=="3"} {set tag add} {set tag $dtag}
183
+ if {$key4=="3"} {set tag add} {set tag -}
180184
if {$key3=="1"} {
181185
.txtC insert end [string range $A 1 end]\n $tag
182186
} elseif {$key3=="2"} {
183187
.txtC insert end [string range $B 1 end]\n chng
184
- } else {
188
+ } elseif {$key3=="X"} {
189
+ .txtC insert end [string range $C 1 end]\n rm
190
+ } else {
185191
.txtC insert end [string range $C 1 end]\n $tag
186192
}
187193
}
188194
if {$key4=="."} {
189195
.lnD insert end \n -
190
- .txtD insert end \n $dtag
196
+ .txtD insert end \n -
191197
} elseif {$key4=="N"} {
192198
.nameD config -text [string range $D 1 end]
193199
} else {
194200
.lnD insert end $lnD\n -
195201
incr lnD
@@ -197,12 +203,14 @@
197203
.txtD insert end [string range $A 1 end]\n -
198204
} elseif {$key4=="2"} {
199205
.txtD insert end [string range $B 1 end]\n chng
200206
} elseif {$key4=="3"} {
201207
.txtD insert end [string range $C 1 end]\n add
208
+ } elseif {$key4=="X"} {
209
+ .txtD insert end [string range $D 1 end]\n rm
202210
} else {
203
- .txtD insert end [string range $D 1 end]\n $dtag
211
+ .txtD insert end [string range $D 1 end]\n -
204212
}
205213
}
206214
}
207215
foreach c [cols] {
208216
set type [colType $c]
209217
--- src/merge.tcl
+++ src/merge.tcl
@@ -122,74 +122,80 @@
122 set lnC 1
123 set lnD 1
124 foreach {A B C D} $mergetxt {
125 set key1 [string index $A 0]
126 if {$key1=="S"} {
127 set N [string range $A 1 end]
128 incr lnA $N
129 incr lnB $N
130 incr lnC $N
131 incr lnD $N
132 .lnA insert end ...\n hrln
133 .txtA insert end [string repeat . 30]\n hrtxt
134 .lnB insert end ...\n hrln
135 .txtB insert end [string repeat . 30]\n hrtxt
136 .lnC insert end ...\n hrln
137 .txtC insert end [string repeat . 30]\n hrtxt
138 .lnD insert end ...\n hrln
139 .txtD insert end [string repeat . 30]\n hrtxt
140 continue
141 }
142 set key2 [string index $B 0]
143 set key3 [string index $C 0]
144 set key4 [string index $D 0]
145 if {$key4=="X"} {set dtag rm} {set dtag -}
146 if {$key1=="."} {
147 .lnA insert end \n -
148 .txtA insert end \n $dtag
149 } elseif {$key1=="N"} {
150 .nameA config -text [string range $A 1 end]
151 } else {
152 .lnA insert end $lnA\n -
153 incr lnA
154 .txtA insert end [string range $A 1 end]\n $dtag
 
 
 
 
155 }
156 if {$key2=="."} {
157 .lnB insert end \n -
158 .txtB insert end \n $dtag
159 } elseif {$key2=="N"} {
160 .nameB config -text [string range $B 1 end]
161 } else {
162 .lnB insert end $lnB\n -
163 incr lnB
164 if {$key4=="2"} {set tag chng} {set tag $dtag}
165 if {$key2=="1"} {
166 .txtB insert end [string range $A 1 end]\n $tag
 
 
167 } else {
168 .txtB insert end [string range $B 1 end]\n $tag
169 }
170 }
171 if {$key3=="."} {
172 .lnC insert end \n -
173 .txtC insert end \n $dtag
174 } elseif {$key3=="N"} {
175 .nameC config -text [string range $C 1 end]
176 } else {
177 .lnC insert end $lnC\n -
178 incr lnC
179 if {$key4=="3"} {set tag add} {set tag $dtag}
180 if {$key3=="1"} {
181 .txtC insert end [string range $A 1 end]\n $tag
182 } elseif {$key3=="2"} {
183 .txtC insert end [string range $B 1 end]\n chng
184 } else {
 
 
185 .txtC insert end [string range $C 1 end]\n $tag
186 }
187 }
188 if {$key4=="."} {
189 .lnD insert end \n -
190 .txtD insert end \n $dtag
191 } elseif {$key4=="N"} {
192 .nameD config -text [string range $D 1 end]
193 } else {
194 .lnD insert end $lnD\n -
195 incr lnD
@@ -197,12 +203,14 @@
197 .txtD insert end [string range $A 1 end]\n -
198 } elseif {$key4=="2"} {
199 .txtD insert end [string range $B 1 end]\n chng
200 } elseif {$key4=="3"} {
201 .txtD insert end [string range $C 1 end]\n add
 
 
202 } else {
203 .txtD insert end [string range $D 1 end]\n $dtag
204 }
205 }
206 }
207 foreach c [cols] {
208 set type [colType $c]
209
--- src/merge.tcl
+++ src/merge.tcl
@@ -122,74 +122,80 @@
122 set lnC 1
123 set lnD 1
124 foreach {A B C D} $mergetxt {
125 set key1 [string index $A 0]
126 if {$key1=="S"} {
127 scan [string range $A 1 end] "%d %d %d %d" nA nB nC nD
128 foreach x {A B C D} {
129 set N [set n$x]
130 incr ln$x $N
131 if {$N>0} {
132 .ln$x insert end ...\n hrln
133 .txt$x insert end [string repeat . 30]\n hrtxt
134 } else {
135 .ln$x insert end \n hrln
136 .txt$x insert end \n hrtxt
137 }
138 }
 
139 continue
140 }
141 set key2 [string index $B 0]
142 set key3 [string index $C 0]
143 set key4 [string index $D 0]
 
144 if {$key1=="."} {
145 .lnA insert end \n -
146 .txtA insert end \n -
147 } elseif {$key1=="N"} {
148 .nameA config -text [string range $A 1 end]
149 } else {
150 .lnA insert end $lnA\n -
151 incr lnA
152 if {$key1=="X"} {
153 .txtA insert end [string range $A 1 end]\n rm
154 } else {
155 .txtA insert end [string range $A 1 end]\n -
156 }
157 }
158 if {$key2=="."} {
159 .lnB insert end \n -
160 .txtB insert end \n -
161 } elseif {$key2=="N"} {
162 .nameB config -text [string range $B 1 end]
163 } else {
164 .lnB insert end $lnB\n -
165 incr lnB
166 if {$key4=="2"} {set tag chng} {set tag -}
167 if {$key2=="1"} {
168 .txtB insert end [string range $A 1 end]\n $tag
169 } elseif {$key2=="X"} {
170 .txtB insert end [string range $B 1 end]\n rm
171 } else {
172 .txtB insert end [string range $B 1 end]\n $tag
173 }
174 }
175 if {$key3=="."} {
176 .lnC insert end \n -
177 .txtC insert end \n -
178 } elseif {$key3=="N"} {
179 .nameC config -text [string range $C 1 end]
180 } else {
181 .lnC insert end $lnC\n -
182 incr lnC
183 if {$key4=="3"} {set tag add} {set tag -}
184 if {$key3=="1"} {
185 .txtC insert end [string range $A 1 end]\n $tag
186 } elseif {$key3=="2"} {
187 .txtC insert end [string range $B 1 end]\n chng
188 } elseif {$key3=="X"} {
189 .txtC insert end [string range $C 1 end]\n rm
190 } else {
191 .txtC insert end [string range $C 1 end]\n $tag
192 }
193 }
194 if {$key4=="."} {
195 .lnD insert end \n -
196 .txtD insert end \n -
197 } elseif {$key4=="N"} {
198 .nameD config -text [string range $D 1 end]
199 } else {
200 .lnD insert end $lnD\n -
201 incr lnD
@@ -197,12 +203,14 @@
203 .txtD insert end [string range $A 1 end]\n -
204 } elseif {$key4=="2"} {
205 .txtD insert end [string range $B 1 end]\n chng
206 } elseif {$key4=="3"} {
207 .txtD insert end [string range $C 1 end]\n add
208 } elseif {$key4=="X"} {
209 .txtD insert end [string range $D 1 end]\n rm
210 } else {
211 .txtD insert end [string range $D 1 end]\n -
212 }
213 }
214 }
215 foreach c [cols] {
216 set type [colType $c]
217
+55 -40
--- src/merge3.c
+++ src/merge3.c
@@ -81,10 +81,11 @@
8181
** Text of boundary markers for merge conflicts.
8282
*/
8383
static const char *const mergeMarker[] = {
8484
/*123456789 123456789 123456789 123456789 123456789 123456789 123456789*/
8585
"<<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<",
86
+ "####### SUGGESTED CONFLICT RESOLUTION follows ###################",
8687
"||||||| COMMON ANCESTOR content follows |||||||||||||||||||||||||",
8788
"======= MERGED IN content follows ===============================",
8889
">>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
8990
};
9091
@@ -395,20 +396,31 @@
395396
MergeBuilder *p,
396397
unsigned int nPivot,
397398
unsigned int nV1,
398399
unsigned int nV2
399400
){
400
- append_merge_mark(p->pOut, 0, p->lnV1, p->useCrLf);
401
+ int nRes; /* Lines in the computed conflict resolution */
402
+ Blob res; /* Text of the conflict resolution */
403
+
404
+ merge_try_to_resolve_conflict(p, nPivot, nV1, nV2, &res);
405
+ nRes = blob_linecount(&res);
406
+
407
+ append_merge_mark(p->pOut, 0, p->lnV1+1, p->useCrLf);
401408
blob_copy_lines(p->pOut, p->pV1, nV1); p->lnV1 += nV1;
402409
403
- append_merge_mark(p->pOut, 1, p->lnPivot, p->useCrLf);
410
+ if( nRes>0 ){
411
+ append_merge_mark(p->pOut, 1, 10000+nRes, p->useCrLf);
412
+ blob_copy_lines(p->pOut, &res, nRes);
413
+ }
414
+
415
+ append_merge_mark(p->pOut, 2, p->lnPivot+1, p->useCrLf);
404416
blob_copy_lines(p->pOut, p->pPivot, nPivot); p->lnPivot += nPivot;
405417
406
- append_merge_mark(p->pOut, 2, p->lnV2, p->useCrLf);
418
+ append_merge_mark(p->pOut, 3, p->lnV2+1, p->useCrLf);
407419
blob_copy_lines(p->pOut, p->pV2, nV2); p->lnV2 += nV2;
408420
409
- append_merge_mark(p->pOut, 3, -1, p->useCrLf);
421
+ append_merge_mark(p->pOut, 4, -1, p->useCrLf);
410422
}
411423
static void mergebuilder_init_text(MergeBuilder *p){
412424
mergebuilder_init(p);
413425
p->xStart = txtStart;
414426
p->xSame = txtSame;
@@ -430,11 +442,11 @@
430442
** N Name of the file.
431443
** T Literal text follows that should have a \n terminator.
432444
** R Literal text follows that needs a \r\n terminator.
433445
** X Merge conflict.
434446
** Z Literal text without a line terminator.
435
-** S Skipped lines in all 4 files.
447
+** S Skipped lines. Followed by number of lines to skip.
436448
** 1 Text is a copy of token 1
437449
** 2 Use data from data-token 2
438450
** 3 Use data from data-token 3
439451
*/
440452
@@ -464,24 +476,20 @@
464476
/* Copy one line of text from pIn and append to pOut, encoded as TCL */
465477
static void tclLineOfText(Blob *pOut, Blob *pIn, char cType){
466478
int i, k;
467479
for(i=pIn->iCursor; i<pIn->nUsed && pIn->aData[i]!='\n'; i++){}
468480
if( i==pIn->nUsed ){
469
- blob_append_char(pOut, '"');
470
- blob_append_char(pOut, cType ? cType : 'Z');
471481
k = i;
472482
}else if( i>pIn->iCursor && pIn->aData[i-1]=='\r' ){
473
- blob_append_char(pOut, '"');
474
- blob_append_char(pOut, cType ? cType : 'R');
475483
k = i-1;
476484
i++;
477485
}else{
478
- blob_append_char(pOut, '"');
479
- blob_append_char(pOut, cType ? cType : 'T');
480486
k = i;
481487
i++;
482488
}
489
+ blob_append_char(pOut, '"');
490
+ blob_append_char(pOut, cType);
483491
tclWriteQuotedText(pOut, pIn->aData+pIn->iCursor, k-pIn->iCursor);
484492
pIn->iCursor = i;
485493
blob_append_char(pOut, '"');
486494
}
487495
static void tclStart(MergeBuilder *p){
@@ -504,20 +512,21 @@
504512
int i = 0;
505513
int nSkip;
506514
507515
if( p->lnPivot>=2 || p->lnV1>2 || p->lnV2>2 ){
508516
while( i<N && i<p->nContext ){
509
- tclLineOfText(p->pOut, p->pPivot, 0);
517
+ tclLineOfText(p->pOut, p->pPivot, 'T');
510518
blob_append(p->pOut, " 1 1 1\n", 7);
511519
i++;
512520
}
513521
nSkip = N - p->nContext*2;
514522
}else{
515523
nSkip = N - p->nContext;
516524
}
517525
if( nSkip>0 ){
518
- blob_appendf(p->pOut, "S%d . . .\n", nSkip);
526
+ blob_appendf(p->pOut, "\"S%d %d %d %d\" . . .\n",
527
+ nSkip, nSkip, nSkip, nSkip);
519528
blob_copy_lines(0, p->pPivot, nSkip);
520529
i += nSkip;
521530
}
522531
523532
p->lnPivot += N;
@@ -524,11 +533,11 @@
524533
p->lnV1 += N;
525534
p->lnV2 += N;
526535
527536
if( p->lnPivot<p->mxPivot || p->lnV1<p->mxV1 || p->lnV2<p->mxV2 ){
528537
while( i<N ){
529
- tclLineOfText(p->pOut, p->pPivot, 0);
538
+ tclLineOfText(p->pOut, p->pPivot, 'T');
530539
blob_append(p->pOut, " 1 1 1\n", 7);
531540
i++;
532541
}
533542
}
534543
@@ -536,23 +545,23 @@
536545
blob_copy_lines(0, p->pV2, N);
537546
}
538547
static void tclChngV1(MergeBuilder *p, unsigned int nPivot, unsigned int nV1){
539548
int i;
540549
for(i=0; i<nPivot && i<nV1; i++){
541
- tclLineOfText(p->pOut, p->pPivot, 0);
550
+ tclLineOfText(p->pOut, p->pPivot, 'T');
542551
blob_append_char(p->pOut, ' ');
543
- tclLineOfText(p->pOut, p->pV1, 0);
552
+ tclLineOfText(p->pOut, p->pV1, 'T');
544553
blob_append(p->pOut, " 1 2\n", 5);
545554
}
546555
while( i<nPivot ){
547
- tclLineOfText(p->pOut, p->pPivot, 0);
556
+ tclLineOfText(p->pOut, p->pPivot, 'T');
548557
blob_append(p->pOut, " . 1 .\n", 7);
549558
i++;
550559
}
551560
while( i<nV1 ){
552561
blob_append(p->pOut, ". ", 2);
553
- tclLineOfText(p->pOut, p->pV1, 0);
562
+ tclLineOfText(p->pOut, p->pV1, 'T');
554563
blob_append(p->pOut, " . 2\n", 5);
555564
i++;
556565
}
557566
p->lnPivot += nPivot;
558567
p->lnV1 += nV1;
@@ -560,23 +569,23 @@
560569
blob_copy_lines(0, p->pV2, nPivot);
561570
}
562571
static void tclChngV2(MergeBuilder *p, unsigned int nPivot, unsigned int nV2){
563572
int i;
564573
for(i=0; i<nPivot && i<nV2; i++){
565
- tclLineOfText(p->pOut, p->pPivot, 0);
574
+ tclLineOfText(p->pOut, p->pPivot, 'T');
566575
blob_append(p->pOut, " 1 ", 3);
567
- tclLineOfText(p->pOut, p->pV2, 0);
576
+ tclLineOfText(p->pOut, p->pV2, 'T');
568577
blob_append(p->pOut, " 3\n", 3);
569578
}
570579
while( i<nPivot ){
571
- tclLineOfText(p->pOut, p->pPivot, 0);
580
+ tclLineOfText(p->pOut, p->pPivot, 'T');
572581
blob_append(p->pOut, " 1 . .\n", 7);
573582
i++;
574583
}
575584
while( i<nV2 ){
576585
blob_append(p->pOut, ". . ", 4);
577
- tclLineOfText(p->pOut, p->pV2, 0);
586
+ tclLineOfText(p->pOut, p->pV2, 'T');
578587
blob_append(p->pOut, " 3\n", 3);
579588
i++;
580589
}
581590
p->lnPivot += nPivot;
582591
p->lnV1 += nPivot;
@@ -584,23 +593,23 @@
584593
blob_copy_lines(0, p->pV1, nPivot);
585594
}
586595
static void tclChngBoth(MergeBuilder *p, unsigned int nPivot, unsigned int nV){
587596
int i;
588597
for(i=0; i<nPivot && i<nV; i++){
589
- tclLineOfText(p->pOut, p->pPivot, 0);
598
+ tclLineOfText(p->pOut, p->pPivot, 'T');
590599
blob_append_char(p->pOut, ' ');
591
- tclLineOfText(p->pOut, p->pV1, 0);
600
+ tclLineOfText(p->pOut, p->pV1, 'T');
592601
blob_append(p->pOut, " 2 2\n", 5);
593602
}
594603
while( i<nPivot ){
595
- tclLineOfText(p->pOut, p->pPivot, 0);
604
+ tclLineOfText(p->pOut, p->pPivot, 'T');
596605
blob_append(p->pOut, " . . .\n", 7);
597606
i++;
598607
}
599608
while( i<nV ){
600609
blob_append(p->pOut, ". ", 2);
601
- tclLineOfText(p->pOut, p->pV1, 0);
610
+ tclLineOfText(p->pOut, p->pV1, 'T');
602611
blob_append(p->pOut, " 2 2\n", 5);
603612
i++;
604613
}
605614
p->lnPivot += nPivot;
606615
p->lnV1 += nV;
@@ -613,45 +622,51 @@
613622
unsigned int nV1,
614623
unsigned int nV2
615624
){
616625
int mx = nPivot;
617626
int i;
618
- int nOut;
619
- Blob out;
627
+ int nRes;
628
+ Blob res;
620629
621
- merge_try_to_resolve_conflict(p, nPivot, nV1, nV2, &out);
622
- nOut = blob_linecount(&out);
630
+ merge_try_to_resolve_conflict(p, nPivot, nV1, nV2, &res);
631
+ nRes = blob_linecount(&res);
623632
if( nV1>mx ) mx = nV1;
624633
if( nV2>mx ) mx = nV2;
625
- if( nOut>mx ) mx = nOut;
634
+ if( nRes>mx ) mx = nRes;
635
+ if( nRes>0 ){
636
+ blob_appendf(p->pOut, "\"S0 0 0 %d\" . . .\n", nV2+2);
637
+ }
626638
for(i=0; i<mx; i++){
627639
if( i<nPivot ){
628
- tclLineOfText(p->pOut, p->pPivot, 0);
640
+ tclLineOfText(p->pOut, p->pPivot, 'X');
629641
}else{
630642
blob_append_char(p->pOut, '.');
631643
}
632644
blob_append_char(p->pOut, ' ');
633645
if( i<nV1 ){
634
- tclLineOfText(p->pOut, p->pV1, 0);
646
+ tclLineOfText(p->pOut, p->pV1, 'X');
635647
}else{
636648
blob_append_char(p->pOut, '.');
637649
}
638650
blob_append_char(p->pOut, ' ');
639651
if( i<nV2 ){
640
- tclLineOfText(p->pOut, p->pV2, 0);
652
+ tclLineOfText(p->pOut, p->pV2, 'X');
641653
}else{
642654
blob_append_char(p->pOut, '.');
643655
}
644
- if( i<nOut ){
656
+ if( i<nRes ){
645657
blob_append_char(p->pOut, ' ');
646
- tclLineOfText(p->pOut, &out, 'X');
658
+ tclLineOfText(p->pOut, &res, 'X');
647659
blob_append_char(p->pOut, '\n');
648660
}else{
649
- blob_append(p->pOut, " X\n", 3);
661
+ blob_append(p->pOut, " .\n", 3);
662
+ }
663
+ if( i==nRes-1 ){
664
+ blob_appendf(p->pOut, "\"S0 0 0 %d\" . . .\n", nPivot+nV1+3);
650665
}
651666
}
652
- blob_reset(&out);
667
+ blob_reset(&res);
653668
p->lnPivot += nPivot;
654669
p->lnV1 += nV1;
655670
p->lnV2 += nV2;
656671
}
657672
void mergebuilder_init_tcl(MergeBuilder *p){
@@ -1111,17 +1126,17 @@
11111126
11121127
#if INTERFACE
11131128
/*
11141129
** Flags to the 3-way merger
11151130
*/
1116
-#define MERGE_DRYRUN 0x0001
1131
+#define MERGE_DRYRUN 0x0001
11171132
/*
11181133
** The MERGE_KEEP_FILES flag specifies that merge_3way() should retain
11191134
** its temporary files on error. By default they are removed after the
11201135
** merge, regardless of success or failure.
11211136
*/
1122
-#define MERGE_KEEP_FILES 0x0002
1137
+#define MERGE_KEEP_FILES 0x0002
11231138
#endif
11241139
11251140
11261141
/*
11271142
** This routine is a wrapper around merge_three_blobs() with the following
11281143
--- src/merge3.c
+++ src/merge3.c
@@ -81,10 +81,11 @@
81 ** Text of boundary markers for merge conflicts.
82 */
83 static const char *const mergeMarker[] = {
84 /*123456789 123456789 123456789 123456789 123456789 123456789 123456789*/
85 "<<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<",
 
86 "||||||| COMMON ANCESTOR content follows |||||||||||||||||||||||||",
87 "======= MERGED IN content follows ===============================",
88 ">>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
89 };
90
@@ -395,20 +396,31 @@
395 MergeBuilder *p,
396 unsigned int nPivot,
397 unsigned int nV1,
398 unsigned int nV2
399 ){
400 append_merge_mark(p->pOut, 0, p->lnV1, p->useCrLf);
 
 
 
 
 
 
401 blob_copy_lines(p->pOut, p->pV1, nV1); p->lnV1 += nV1;
402
403 append_merge_mark(p->pOut, 1, p->lnPivot, p->useCrLf);
 
 
 
 
 
404 blob_copy_lines(p->pOut, p->pPivot, nPivot); p->lnPivot += nPivot;
405
406 append_merge_mark(p->pOut, 2, p->lnV2, p->useCrLf);
407 blob_copy_lines(p->pOut, p->pV2, nV2); p->lnV2 += nV2;
408
409 append_merge_mark(p->pOut, 3, -1, p->useCrLf);
410 }
411 static void mergebuilder_init_text(MergeBuilder *p){
412 mergebuilder_init(p);
413 p->xStart = txtStart;
414 p->xSame = txtSame;
@@ -430,11 +442,11 @@
430 ** N Name of the file.
431 ** T Literal text follows that should have a \n terminator.
432 ** R Literal text follows that needs a \r\n terminator.
433 ** X Merge conflict.
434 ** Z Literal text without a line terminator.
435 ** S Skipped lines in all 4 files.
436 ** 1 Text is a copy of token 1
437 ** 2 Use data from data-token 2
438 ** 3 Use data from data-token 3
439 */
440
@@ -464,24 +476,20 @@
464 /* Copy one line of text from pIn and append to pOut, encoded as TCL */
465 static void tclLineOfText(Blob *pOut, Blob *pIn, char cType){
466 int i, k;
467 for(i=pIn->iCursor; i<pIn->nUsed && pIn->aData[i]!='\n'; i++){}
468 if( i==pIn->nUsed ){
469 blob_append_char(pOut, '"');
470 blob_append_char(pOut, cType ? cType : 'Z');
471 k = i;
472 }else if( i>pIn->iCursor && pIn->aData[i-1]=='\r' ){
473 blob_append_char(pOut, '"');
474 blob_append_char(pOut, cType ? cType : 'R');
475 k = i-1;
476 i++;
477 }else{
478 blob_append_char(pOut, '"');
479 blob_append_char(pOut, cType ? cType : 'T');
480 k = i;
481 i++;
482 }
 
 
483 tclWriteQuotedText(pOut, pIn->aData+pIn->iCursor, k-pIn->iCursor);
484 pIn->iCursor = i;
485 blob_append_char(pOut, '"');
486 }
487 static void tclStart(MergeBuilder *p){
@@ -504,20 +512,21 @@
504 int i = 0;
505 int nSkip;
506
507 if( p->lnPivot>=2 || p->lnV1>2 || p->lnV2>2 ){
508 while( i<N && i<p->nContext ){
509 tclLineOfText(p->pOut, p->pPivot, 0);
510 blob_append(p->pOut, " 1 1 1\n", 7);
511 i++;
512 }
513 nSkip = N - p->nContext*2;
514 }else{
515 nSkip = N - p->nContext;
516 }
517 if( nSkip>0 ){
518 blob_appendf(p->pOut, "S%d . . .\n", nSkip);
 
519 blob_copy_lines(0, p->pPivot, nSkip);
520 i += nSkip;
521 }
522
523 p->lnPivot += N;
@@ -524,11 +533,11 @@
524 p->lnV1 += N;
525 p->lnV2 += N;
526
527 if( p->lnPivot<p->mxPivot || p->lnV1<p->mxV1 || p->lnV2<p->mxV2 ){
528 while( i<N ){
529 tclLineOfText(p->pOut, p->pPivot, 0);
530 blob_append(p->pOut, " 1 1 1\n", 7);
531 i++;
532 }
533 }
534
@@ -536,23 +545,23 @@
536 blob_copy_lines(0, p->pV2, N);
537 }
538 static void tclChngV1(MergeBuilder *p, unsigned int nPivot, unsigned int nV1){
539 int i;
540 for(i=0; i<nPivot && i<nV1; i++){
541 tclLineOfText(p->pOut, p->pPivot, 0);
542 blob_append_char(p->pOut, ' ');
543 tclLineOfText(p->pOut, p->pV1, 0);
544 blob_append(p->pOut, " 1 2\n", 5);
545 }
546 while( i<nPivot ){
547 tclLineOfText(p->pOut, p->pPivot, 0);
548 blob_append(p->pOut, " . 1 .\n", 7);
549 i++;
550 }
551 while( i<nV1 ){
552 blob_append(p->pOut, ". ", 2);
553 tclLineOfText(p->pOut, p->pV1, 0);
554 blob_append(p->pOut, " . 2\n", 5);
555 i++;
556 }
557 p->lnPivot += nPivot;
558 p->lnV1 += nV1;
@@ -560,23 +569,23 @@
560 blob_copy_lines(0, p->pV2, nPivot);
561 }
562 static void tclChngV2(MergeBuilder *p, unsigned int nPivot, unsigned int nV2){
563 int i;
564 for(i=0; i<nPivot && i<nV2; i++){
565 tclLineOfText(p->pOut, p->pPivot, 0);
566 blob_append(p->pOut, " 1 ", 3);
567 tclLineOfText(p->pOut, p->pV2, 0);
568 blob_append(p->pOut, " 3\n", 3);
569 }
570 while( i<nPivot ){
571 tclLineOfText(p->pOut, p->pPivot, 0);
572 blob_append(p->pOut, " 1 . .\n", 7);
573 i++;
574 }
575 while( i<nV2 ){
576 blob_append(p->pOut, ". . ", 4);
577 tclLineOfText(p->pOut, p->pV2, 0);
578 blob_append(p->pOut, " 3\n", 3);
579 i++;
580 }
581 p->lnPivot += nPivot;
582 p->lnV1 += nPivot;
@@ -584,23 +593,23 @@
584 blob_copy_lines(0, p->pV1, nPivot);
585 }
586 static void tclChngBoth(MergeBuilder *p, unsigned int nPivot, unsigned int nV){
587 int i;
588 for(i=0; i<nPivot && i<nV; i++){
589 tclLineOfText(p->pOut, p->pPivot, 0);
590 blob_append_char(p->pOut, ' ');
591 tclLineOfText(p->pOut, p->pV1, 0);
592 blob_append(p->pOut, " 2 2\n", 5);
593 }
594 while( i<nPivot ){
595 tclLineOfText(p->pOut, p->pPivot, 0);
596 blob_append(p->pOut, " . . .\n", 7);
597 i++;
598 }
599 while( i<nV ){
600 blob_append(p->pOut, ". ", 2);
601 tclLineOfText(p->pOut, p->pV1, 0);
602 blob_append(p->pOut, " 2 2\n", 5);
603 i++;
604 }
605 p->lnPivot += nPivot;
606 p->lnV1 += nV;
@@ -613,45 +622,51 @@
613 unsigned int nV1,
614 unsigned int nV2
615 ){
616 int mx = nPivot;
617 int i;
618 int nOut;
619 Blob out;
620
621 merge_try_to_resolve_conflict(p, nPivot, nV1, nV2, &out);
622 nOut = blob_linecount(&out);
623 if( nV1>mx ) mx = nV1;
624 if( nV2>mx ) mx = nV2;
625 if( nOut>mx ) mx = nOut;
 
 
 
626 for(i=0; i<mx; i++){
627 if( i<nPivot ){
628 tclLineOfText(p->pOut, p->pPivot, 0);
629 }else{
630 blob_append_char(p->pOut, '.');
631 }
632 blob_append_char(p->pOut, ' ');
633 if( i<nV1 ){
634 tclLineOfText(p->pOut, p->pV1, 0);
635 }else{
636 blob_append_char(p->pOut, '.');
637 }
638 blob_append_char(p->pOut, ' ');
639 if( i<nV2 ){
640 tclLineOfText(p->pOut, p->pV2, 0);
641 }else{
642 blob_append_char(p->pOut, '.');
643 }
644 if( i<nOut ){
645 blob_append_char(p->pOut, ' ');
646 tclLineOfText(p->pOut, &out, 'X');
647 blob_append_char(p->pOut, '\n');
648 }else{
649 blob_append(p->pOut, " X\n", 3);
 
 
 
650 }
651 }
652 blob_reset(&out);
653 p->lnPivot += nPivot;
654 p->lnV1 += nV1;
655 p->lnV2 += nV2;
656 }
657 void mergebuilder_init_tcl(MergeBuilder *p){
@@ -1111,17 +1126,17 @@
1111
1112 #if INTERFACE
1113 /*
1114 ** Flags to the 3-way merger
1115 */
1116 #define MERGE_DRYRUN 0x0001
1117 /*
1118 ** The MERGE_KEEP_FILES flag specifies that merge_3way() should retain
1119 ** its temporary files on error. By default they are removed after the
1120 ** merge, regardless of success or failure.
1121 */
1122 #define MERGE_KEEP_FILES 0x0002
1123 #endif
1124
1125
1126 /*
1127 ** This routine is a wrapper around merge_three_blobs() with the following
1128
--- src/merge3.c
+++ src/merge3.c
@@ -81,10 +81,11 @@
81 ** Text of boundary markers for merge conflicts.
82 */
83 static const char *const mergeMarker[] = {
84 /*123456789 123456789 123456789 123456789 123456789 123456789 123456789*/
85 "<<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<",
86 "####### SUGGESTED CONFLICT RESOLUTION follows ###################",
87 "||||||| COMMON ANCESTOR content follows |||||||||||||||||||||||||",
88 "======= MERGED IN content follows ===============================",
89 ">>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
90 };
91
@@ -395,20 +396,31 @@
396 MergeBuilder *p,
397 unsigned int nPivot,
398 unsigned int nV1,
399 unsigned int nV2
400 ){
401 int nRes; /* Lines in the computed conflict resolution */
402 Blob res; /* Text of the conflict resolution */
403
404 merge_try_to_resolve_conflict(p, nPivot, nV1, nV2, &res);
405 nRes = blob_linecount(&res);
406
407 append_merge_mark(p->pOut, 0, p->lnV1+1, p->useCrLf);
408 blob_copy_lines(p->pOut, p->pV1, nV1); p->lnV1 += nV1;
409
410 if( nRes>0 ){
411 append_merge_mark(p->pOut, 1, 10000+nRes, p->useCrLf);
412 blob_copy_lines(p->pOut, &res, nRes);
413 }
414
415 append_merge_mark(p->pOut, 2, p->lnPivot+1, p->useCrLf);
416 blob_copy_lines(p->pOut, p->pPivot, nPivot); p->lnPivot += nPivot;
417
418 append_merge_mark(p->pOut, 3, p->lnV2+1, p->useCrLf);
419 blob_copy_lines(p->pOut, p->pV2, nV2); p->lnV2 += nV2;
420
421 append_merge_mark(p->pOut, 4, -1, p->useCrLf);
422 }
423 static void mergebuilder_init_text(MergeBuilder *p){
424 mergebuilder_init(p);
425 p->xStart = txtStart;
426 p->xSame = txtSame;
@@ -430,11 +442,11 @@
442 ** N Name of the file.
443 ** T Literal text follows that should have a \n terminator.
444 ** R Literal text follows that needs a \r\n terminator.
445 ** X Merge conflict.
446 ** Z Literal text without a line terminator.
447 ** S Skipped lines. Followed by number of lines to skip.
448 ** 1 Text is a copy of token 1
449 ** 2 Use data from data-token 2
450 ** 3 Use data from data-token 3
451 */
452
@@ -464,24 +476,20 @@
476 /* Copy one line of text from pIn and append to pOut, encoded as TCL */
477 static void tclLineOfText(Blob *pOut, Blob *pIn, char cType){
478 int i, k;
479 for(i=pIn->iCursor; i<pIn->nUsed && pIn->aData[i]!='\n'; i++){}
480 if( i==pIn->nUsed ){
 
 
481 k = i;
482 }else if( i>pIn->iCursor && pIn->aData[i-1]=='\r' ){
 
 
483 k = i-1;
484 i++;
485 }else{
 
 
486 k = i;
487 i++;
488 }
489 blob_append_char(pOut, '"');
490 blob_append_char(pOut, cType);
491 tclWriteQuotedText(pOut, pIn->aData+pIn->iCursor, k-pIn->iCursor);
492 pIn->iCursor = i;
493 blob_append_char(pOut, '"');
494 }
495 static void tclStart(MergeBuilder *p){
@@ -504,20 +512,21 @@
512 int i = 0;
513 int nSkip;
514
515 if( p->lnPivot>=2 || p->lnV1>2 || p->lnV2>2 ){
516 while( i<N && i<p->nContext ){
517 tclLineOfText(p->pOut, p->pPivot, 'T');
518 blob_append(p->pOut, " 1 1 1\n", 7);
519 i++;
520 }
521 nSkip = N - p->nContext*2;
522 }else{
523 nSkip = N - p->nContext;
524 }
525 if( nSkip>0 ){
526 blob_appendf(p->pOut, "\"S%d %d %d %d\" . . .\n",
527 nSkip, nSkip, nSkip, nSkip);
528 blob_copy_lines(0, p->pPivot, nSkip);
529 i += nSkip;
530 }
531
532 p->lnPivot += N;
@@ -524,11 +533,11 @@
533 p->lnV1 += N;
534 p->lnV2 += N;
535
536 if( p->lnPivot<p->mxPivot || p->lnV1<p->mxV1 || p->lnV2<p->mxV2 ){
537 while( i<N ){
538 tclLineOfText(p->pOut, p->pPivot, 'T');
539 blob_append(p->pOut, " 1 1 1\n", 7);
540 i++;
541 }
542 }
543
@@ -536,23 +545,23 @@
545 blob_copy_lines(0, p->pV2, N);
546 }
547 static void tclChngV1(MergeBuilder *p, unsigned int nPivot, unsigned int nV1){
548 int i;
549 for(i=0; i<nPivot && i<nV1; i++){
550 tclLineOfText(p->pOut, p->pPivot, 'T');
551 blob_append_char(p->pOut, ' ');
552 tclLineOfText(p->pOut, p->pV1, 'T');
553 blob_append(p->pOut, " 1 2\n", 5);
554 }
555 while( i<nPivot ){
556 tclLineOfText(p->pOut, p->pPivot, 'T');
557 blob_append(p->pOut, " . 1 .\n", 7);
558 i++;
559 }
560 while( i<nV1 ){
561 blob_append(p->pOut, ". ", 2);
562 tclLineOfText(p->pOut, p->pV1, 'T');
563 blob_append(p->pOut, " . 2\n", 5);
564 i++;
565 }
566 p->lnPivot += nPivot;
567 p->lnV1 += nV1;
@@ -560,23 +569,23 @@
569 blob_copy_lines(0, p->pV2, nPivot);
570 }
571 static void tclChngV2(MergeBuilder *p, unsigned int nPivot, unsigned int nV2){
572 int i;
573 for(i=0; i<nPivot && i<nV2; i++){
574 tclLineOfText(p->pOut, p->pPivot, 'T');
575 blob_append(p->pOut, " 1 ", 3);
576 tclLineOfText(p->pOut, p->pV2, 'T');
577 blob_append(p->pOut, " 3\n", 3);
578 }
579 while( i<nPivot ){
580 tclLineOfText(p->pOut, p->pPivot, 'T');
581 blob_append(p->pOut, " 1 . .\n", 7);
582 i++;
583 }
584 while( i<nV2 ){
585 blob_append(p->pOut, ". . ", 4);
586 tclLineOfText(p->pOut, p->pV2, 'T');
587 blob_append(p->pOut, " 3\n", 3);
588 i++;
589 }
590 p->lnPivot += nPivot;
591 p->lnV1 += nPivot;
@@ -584,23 +593,23 @@
593 blob_copy_lines(0, p->pV1, nPivot);
594 }
595 static void tclChngBoth(MergeBuilder *p, unsigned int nPivot, unsigned int nV){
596 int i;
597 for(i=0; i<nPivot && i<nV; i++){
598 tclLineOfText(p->pOut, p->pPivot, 'T');
599 blob_append_char(p->pOut, ' ');
600 tclLineOfText(p->pOut, p->pV1, 'T');
601 blob_append(p->pOut, " 2 2\n", 5);
602 }
603 while( i<nPivot ){
604 tclLineOfText(p->pOut, p->pPivot, 'T');
605 blob_append(p->pOut, " . . .\n", 7);
606 i++;
607 }
608 while( i<nV ){
609 blob_append(p->pOut, ". ", 2);
610 tclLineOfText(p->pOut, p->pV1, 'T');
611 blob_append(p->pOut, " 2 2\n", 5);
612 i++;
613 }
614 p->lnPivot += nPivot;
615 p->lnV1 += nV;
@@ -613,45 +622,51 @@
622 unsigned int nV1,
623 unsigned int nV2
624 ){
625 int mx = nPivot;
626 int i;
627 int nRes;
628 Blob res;
629
630 merge_try_to_resolve_conflict(p, nPivot, nV1, nV2, &res);
631 nRes = blob_linecount(&res);
632 if( nV1>mx ) mx = nV1;
633 if( nV2>mx ) mx = nV2;
634 if( nRes>mx ) mx = nRes;
635 if( nRes>0 ){
636 blob_appendf(p->pOut, "\"S0 0 0 %d\" . . .\n", nV2+2);
637 }
638 for(i=0; i<mx; i++){
639 if( i<nPivot ){
640 tclLineOfText(p->pOut, p->pPivot, 'X');
641 }else{
642 blob_append_char(p->pOut, '.');
643 }
644 blob_append_char(p->pOut, ' ');
645 if( i<nV1 ){
646 tclLineOfText(p->pOut, p->pV1, 'X');
647 }else{
648 blob_append_char(p->pOut, '.');
649 }
650 blob_append_char(p->pOut, ' ');
651 if( i<nV2 ){
652 tclLineOfText(p->pOut, p->pV2, 'X');
653 }else{
654 blob_append_char(p->pOut, '.');
655 }
656 if( i<nRes ){
657 blob_append_char(p->pOut, ' ');
658 tclLineOfText(p->pOut, &res, 'X');
659 blob_append_char(p->pOut, '\n');
660 }else{
661 blob_append(p->pOut, " .\n", 3);
662 }
663 if( i==nRes-1 ){
664 blob_appendf(p->pOut, "\"S0 0 0 %d\" . . .\n", nPivot+nV1+3);
665 }
666 }
667 blob_reset(&res);
668 p->lnPivot += nPivot;
669 p->lnV1 += nV1;
670 p->lnV2 += nV2;
671 }
672 void mergebuilder_init_tcl(MergeBuilder *p){
@@ -1111,17 +1126,17 @@
1126
1127 #if INTERFACE
1128 /*
1129 ** Flags to the 3-way merger
1130 */
1131 #define MERGE_DRYRUN 0x0001
1132 /*
1133 ** The MERGE_KEEP_FILES flag specifies that merge_3way() should retain
1134 ** its temporary files on error. By default they are removed after the
1135 ** merge, regardless of success or failure.
1136 */
1137 #define MERGE_KEEP_FILES 0x0002
1138 #endif
1139
1140
1141 /*
1142 ** This routine is a wrapper around merge_three_blobs() with the following
1143

Keyboard Shortcuts

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