Fossil SCM

Improvements to handling of line endings and BOM marks when doing a 3-way merge.

drh 2020-08-25 00:01 trunk merge
Commit 88ff2642d3bf0adf1d3f6e43d45c9603d7ef442ea3e034a9765f1743de5adc3d
2 files changed +63 -6 +63 -6
+63 -6
--- src/merge3.c
+++ src/merge3.c
@@ -138,16 +138,47 @@
138138
/*
139139
** Text of boundary markers for merge conflicts.
140140
*/
141141
static const char *const mergeMarker[] = {
142142
/*123456789 123456789 123456789 123456789 123456789 123456789 123456789*/
143
- "<<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<\n",
144
- "||||||| COMMON ANCESTOR content follows ||||||||||||||||||||||||||||\n",
145
- "======= MERGED IN content follows ==================================\n",
146
- ">>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
143
+ "<<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<",
144
+ "||||||| COMMON ANCESTOR content follows ||||||||||||||||||||||||||||",
145
+ "======= MERGED IN content follows ==================================",
146
+ ">>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
147147
};
148148
149
+/*
150
+** Return true if the input blob contains any CR/LF pairs on the first
151
+** ten lines. This should be enough to detect files that use mainly CR/LF
152
+** line endings without causing a performance impact for LF only files.
153
+*/
154
+int contains_crlf(Blob *p){
155
+ int i;
156
+ int j = 0;
157
+ const int maxL = 10; /* Max lines to check */
158
+ const char *z = blob_buffer(p);
159
+ int n = blob_size(p)+1;
160
+ for(i=1; i<n; ){
161
+ if( z[i-1]=='\r' && z[i]=='\n' ) return 1;
162
+ while( i<n && z[i]!='\n' ){ i++; }
163
+ j++;
164
+ if( j>maxL ) return 0;
165
+ }
166
+ return 0;
167
+}
168
+
169
+/*
170
+** Ensure that the text in pBlob ends with a new line.
171
+** If useCrLf is true adds "\r\n" otherwise '\n'.
172
+*/
173
+void ensure_line_end(Blob *pBlob, int useCrLf){
174
+ if( pBlob->nUsed<=0 ) return;
175
+ if( pBlob->aData[pBlob->nUsed-1]!='\n' ){
176
+ if( useCrLf ) blob_append_char(pBlob, '\r');
177
+ blob_append_char(pBlob, '\n');
178
+ }
179
+}
149180
150181
/*
151182
** Do a three-way merge. Initialize pOut to contain the result.
152183
**
153184
** The merge is an edit against pV2. Both pV1 and pV2 have a
@@ -166,10 +197,28 @@
166197
int nCpy, nDel, nIns; /* Number of lines to copy, delete, or insert */
167198
int limit1, limit2; /* Sizes of aC1[] and aC2[] */
168199
int nConflict = 0; /* Number of merge conflicts seen so far */
169200
170201
blob_zero(pOut); /* Merge results stored in pOut */
202
+
203
+ /* If both pV1 and pV2 start with a UTF-8 byte-order-mark (BOM),
204
+ ** keep it in the output. This should be secure enough not to cause
205
+ ** unintended changes to the merged file and consistent with what
206
+ ** users are using in their source files.
207
+ */
208
+ if( starts_with_utf8_bom(pV1, 0) && starts_with_utf8_bom(pV2, 0) ){
209
+ blob_append(pOut, (char*)get_utf8_bom(0), -1);
210
+ }
211
+
212
+ /* Check once to see if both pV1 and pV2 contains CR/LF endings.
213
+ ** If true, CR/LF pair will be used later to append the
214
+ ** boundary markers for merge conflicts.
215
+ */
216
+ int useCrLf = 0;
217
+ if( contains_crlf(pV1) && contains_crlf(pV2) ){
218
+ useCrLf = 1;
219
+ }
171220
172221
/* Compute the edits that occur from pPivot => pV1 (into aC1)
173222
** and pPivot => pV2 (into aC2). Each of the aC1 and aC2 arrays is
174223
** an array of integer triples. Within each triple, the first integer
175224
** is the number of lines of text to copy directly from the pivot,
@@ -269,16 +318,23 @@
269318
while( !ends_at_CPY(&aC1[i1], sz) || !ends_at_CPY(&aC2[i2], sz) ){
270319
sz++;
271320
}
272321
DEBUG( printf("CONFLICT %d\n", sz); )
273322
blob_append(pOut, mergeMarker[0], -1);
323
+ ensure_line_end(pOut, useCrLf);
274324
i1 = output_one_side(pOut, pV1, aC1, i1, sz);
325
+ ensure_line_end(pOut, useCrLf);
275326
blob_append(pOut, mergeMarker[1], -1);
327
+ ensure_line_end(pOut, useCrLf);
276328
blob_copy_lines(pOut, pPivot, sz);
329
+ ensure_line_end(pOut, useCrLf);
277330
blob_append(pOut, mergeMarker[2], -1);
331
+ ensure_line_end(pOut, useCrLf);
278332
i2 = output_one_side(pOut, pV2, aC2, i2, sz);
333
+ ensure_line_end(pOut, useCrLf);
279334
blob_append(pOut, mergeMarker[3], -1);
335
+ ensure_line_end(pOut, useCrLf);
280336
}
281337
282338
/* If we are finished with an edit triple, advance to the next
283339
** triple.
284340
*/
@@ -319,14 +375,15 @@
319375
assert( len==(int)strlen(mergeMarker[2]) );
320376
assert( len==(int)strlen(mergeMarker[3]) );
321377
assert( count(mergeMarker)==4 );
322378
for(i=0; i<n; ){
323379
for(j=0; j<4; j++){
324
- if( memcmp(&z[i], mergeMarker[j], len)==0 ) return 1;
380
+ if( (memcmp(&z[i], mergeMarker[j], len)==0)
381
+ && (i+1==n || z[i+len]=='\n' || z[i+len]=='\r') ) return 1;
325382
}
326383
while( i<n && z[i]!='\n' ){ i++; }
327
- while( i<n && z[i]=='\n' ){ i++; }
384
+ while( i<n && (z[i]=='\n' || z[i]=='\r') ){ i++; }
328385
}
329386
return 0;
330387
}
331388
332389
/*
333390
--- src/merge3.c
+++ src/merge3.c
@@ -138,16 +138,47 @@
138 /*
139 ** Text of boundary markers for merge conflicts.
140 */
141 static const char *const mergeMarker[] = {
142 /*123456789 123456789 123456789 123456789 123456789 123456789 123456789*/
143 "<<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<\n",
144 "||||||| COMMON ANCESTOR content follows ||||||||||||||||||||||||||||\n",
145 "======= MERGED IN content follows ==================================\n",
146 ">>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
147 };
148
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149
150 /*
151 ** Do a three-way merge. Initialize pOut to contain the result.
152 **
153 ** The merge is an edit against pV2. Both pV1 and pV2 have a
@@ -166,10 +197,28 @@
166 int nCpy, nDel, nIns; /* Number of lines to copy, delete, or insert */
167 int limit1, limit2; /* Sizes of aC1[] and aC2[] */
168 int nConflict = 0; /* Number of merge conflicts seen so far */
169
170 blob_zero(pOut); /* Merge results stored in pOut */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
172 /* Compute the edits that occur from pPivot => pV1 (into aC1)
173 ** and pPivot => pV2 (into aC2). Each of the aC1 and aC2 arrays is
174 ** an array of integer triples. Within each triple, the first integer
175 ** is the number of lines of text to copy directly from the pivot,
@@ -269,16 +318,23 @@
269 while( !ends_at_CPY(&aC1[i1], sz) || !ends_at_CPY(&aC2[i2], sz) ){
270 sz++;
271 }
272 DEBUG( printf("CONFLICT %d\n", sz); )
273 blob_append(pOut, mergeMarker[0], -1);
 
274 i1 = output_one_side(pOut, pV1, aC1, i1, sz);
 
275 blob_append(pOut, mergeMarker[1], -1);
 
276 blob_copy_lines(pOut, pPivot, sz);
 
277 blob_append(pOut, mergeMarker[2], -1);
 
278 i2 = output_one_side(pOut, pV2, aC2, i2, sz);
 
279 blob_append(pOut, mergeMarker[3], -1);
 
280 }
281
282 /* If we are finished with an edit triple, advance to the next
283 ** triple.
284 */
@@ -319,14 +375,15 @@
319 assert( len==(int)strlen(mergeMarker[2]) );
320 assert( len==(int)strlen(mergeMarker[3]) );
321 assert( count(mergeMarker)==4 );
322 for(i=0; i<n; ){
323 for(j=0; j<4; j++){
324 if( memcmp(&z[i], mergeMarker[j], len)==0 ) return 1;
 
325 }
326 while( i<n && z[i]!='\n' ){ i++; }
327 while( i<n && z[i]=='\n' ){ i++; }
328 }
329 return 0;
330 }
331
332 /*
333
--- src/merge3.c
+++ src/merge3.c
@@ -138,16 +138,47 @@
138 /*
139 ** Text of boundary markers for merge conflicts.
140 */
141 static const char *const mergeMarker[] = {
142 /*123456789 123456789 123456789 123456789 123456789 123456789 123456789*/
143 "<<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<",
144 "||||||| COMMON ANCESTOR content follows ||||||||||||||||||||||||||||",
145 "======= MERGED IN content follows ==================================",
146 ">>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
147 };
148
149 /*
150 ** Return true if the input blob contains any CR/LF pairs on the first
151 ** ten lines. This should be enough to detect files that use mainly CR/LF
152 ** line endings without causing a performance impact for LF only files.
153 */
154 int contains_crlf(Blob *p){
155 int i;
156 int j = 0;
157 const int maxL = 10; /* Max lines to check */
158 const char *z = blob_buffer(p);
159 int n = blob_size(p)+1;
160 for(i=1; i<n; ){
161 if( z[i-1]=='\r' && z[i]=='\n' ) return 1;
162 while( i<n && z[i]!='\n' ){ i++; }
163 j++;
164 if( j>maxL ) return 0;
165 }
166 return 0;
167 }
168
169 /*
170 ** Ensure that the text in pBlob ends with a new line.
171 ** If useCrLf is true adds "\r\n" otherwise '\n'.
172 */
173 void ensure_line_end(Blob *pBlob, int useCrLf){
174 if( pBlob->nUsed<=0 ) return;
175 if( pBlob->aData[pBlob->nUsed-1]!='\n' ){
176 if( useCrLf ) blob_append_char(pBlob, '\r');
177 blob_append_char(pBlob, '\n');
178 }
179 }
180
181 /*
182 ** Do a three-way merge. Initialize pOut to contain the result.
183 **
184 ** The merge is an edit against pV2. Both pV1 and pV2 have a
@@ -166,10 +197,28 @@
197 int nCpy, nDel, nIns; /* Number of lines to copy, delete, or insert */
198 int limit1, limit2; /* Sizes of aC1[] and aC2[] */
199 int nConflict = 0; /* Number of merge conflicts seen so far */
200
201 blob_zero(pOut); /* Merge results stored in pOut */
202
203 /* If both pV1 and pV2 start with a UTF-8 byte-order-mark (BOM),
204 ** keep it in the output. This should be secure enough not to cause
205 ** unintended changes to the merged file and consistent with what
206 ** users are using in their source files.
207 */
208 if( starts_with_utf8_bom(pV1, 0) && starts_with_utf8_bom(pV2, 0) ){
209 blob_append(pOut, (char*)get_utf8_bom(0), -1);
210 }
211
212 /* Check once to see if both pV1 and pV2 contains CR/LF endings.
213 ** If true, CR/LF pair will be used later to append the
214 ** boundary markers for merge conflicts.
215 */
216 int useCrLf = 0;
217 if( contains_crlf(pV1) && contains_crlf(pV2) ){
218 useCrLf = 1;
219 }
220
221 /* Compute the edits that occur from pPivot => pV1 (into aC1)
222 ** and pPivot => pV2 (into aC2). Each of the aC1 and aC2 arrays is
223 ** an array of integer triples. Within each triple, the first integer
224 ** is the number of lines of text to copy directly from the pivot,
@@ -269,16 +318,23 @@
318 while( !ends_at_CPY(&aC1[i1], sz) || !ends_at_CPY(&aC2[i2], sz) ){
319 sz++;
320 }
321 DEBUG( printf("CONFLICT %d\n", sz); )
322 blob_append(pOut, mergeMarker[0], -1);
323 ensure_line_end(pOut, useCrLf);
324 i1 = output_one_side(pOut, pV1, aC1, i1, sz);
325 ensure_line_end(pOut, useCrLf);
326 blob_append(pOut, mergeMarker[1], -1);
327 ensure_line_end(pOut, useCrLf);
328 blob_copy_lines(pOut, pPivot, sz);
329 ensure_line_end(pOut, useCrLf);
330 blob_append(pOut, mergeMarker[2], -1);
331 ensure_line_end(pOut, useCrLf);
332 i2 = output_one_side(pOut, pV2, aC2, i2, sz);
333 ensure_line_end(pOut, useCrLf);
334 blob_append(pOut, mergeMarker[3], -1);
335 ensure_line_end(pOut, useCrLf);
336 }
337
338 /* If we are finished with an edit triple, advance to the next
339 ** triple.
340 */
@@ -319,14 +375,15 @@
375 assert( len==(int)strlen(mergeMarker[2]) );
376 assert( len==(int)strlen(mergeMarker[3]) );
377 assert( count(mergeMarker)==4 );
378 for(i=0; i<n; ){
379 for(j=0; j<4; j++){
380 if( (memcmp(&z[i], mergeMarker[j], len)==0)
381 && (i+1==n || z[i+len]=='\n' || z[i+len]=='\r') ) return 1;
382 }
383 while( i<n && z[i]!='\n' ){ i++; }
384 while( i<n && (z[i]=='\n' || z[i]=='\r') ){ i++; }
385 }
386 return 0;
387 }
388
389 /*
390
+63 -6
--- src/merge3.c
+++ src/merge3.c
@@ -138,16 +138,47 @@
138138
/*
139139
** Text of boundary markers for merge conflicts.
140140
*/
141141
static const char *const mergeMarker[] = {
142142
/*123456789 123456789 123456789 123456789 123456789 123456789 123456789*/
143
- "<<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<\n",
144
- "||||||| COMMON ANCESTOR content follows ||||||||||||||||||||||||||||\n",
145
- "======= MERGED IN content follows ==================================\n",
146
- ">>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
143
+ "<<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<",
144
+ "||||||| COMMON ANCESTOR content follows ||||||||||||||||||||||||||||",
145
+ "======= MERGED IN content follows ==================================",
146
+ ">>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
147147
};
148148
149
+/*
150
+** Return true if the input blob contains any CR/LF pairs on the first
151
+** ten lines. This should be enough to detect files that use mainly CR/LF
152
+** line endings without causing a performance impact for LF only files.
153
+*/
154
+int contains_crlf(Blob *p){
155
+ int i;
156
+ int j = 0;
157
+ const int maxL = 10; /* Max lines to check */
158
+ const char *z = blob_buffer(p);
159
+ int n = blob_size(p)+1;
160
+ for(i=1; i<n; ){
161
+ if( z[i-1]=='\r' && z[i]=='\n' ) return 1;
162
+ while( i<n && z[i]!='\n' ){ i++; }
163
+ j++;
164
+ if( j>maxL ) return 0;
165
+ }
166
+ return 0;
167
+}
168
+
169
+/*
170
+** Ensure that the text in pBlob ends with a new line.
171
+** If useCrLf is true adds "\r\n" otherwise '\n'.
172
+*/
173
+void ensure_line_end(Blob *pBlob, int useCrLf){
174
+ if( pBlob->nUsed<=0 ) return;
175
+ if( pBlob->aData[pBlob->nUsed-1]!='\n' ){
176
+ if( useCrLf ) blob_append_char(pBlob, '\r');
177
+ blob_append_char(pBlob, '\n');
178
+ }
179
+}
149180
150181
/*
151182
** Do a three-way merge. Initialize pOut to contain the result.
152183
**
153184
** The merge is an edit against pV2. Both pV1 and pV2 have a
@@ -166,10 +197,28 @@
166197
int nCpy, nDel, nIns; /* Number of lines to copy, delete, or insert */
167198
int limit1, limit2; /* Sizes of aC1[] and aC2[] */
168199
int nConflict = 0; /* Number of merge conflicts seen so far */
169200
170201
blob_zero(pOut); /* Merge results stored in pOut */
202
+
203
+ /* If both pV1 and pV2 start with a UTF-8 byte-order-mark (BOM),
204
+ ** keep it in the output. This should be secure enough not to cause
205
+ ** unintended changes to the merged file and consistent with what
206
+ ** users are using in their source files.
207
+ */
208
+ if( starts_with_utf8_bom(pV1, 0) && starts_with_utf8_bom(pV2, 0) ){
209
+ blob_append(pOut, (char*)get_utf8_bom(0), -1);
210
+ }
211
+
212
+ /* Check once to see if both pV1 and pV2 contains CR/LF endings.
213
+ ** If true, CR/LF pair will be used later to append the
214
+ ** boundary markers for merge conflicts.
215
+ */
216
+ int useCrLf = 0;
217
+ if( contains_crlf(pV1) && contains_crlf(pV2) ){
218
+ useCrLf = 1;
219
+ }
171220
172221
/* Compute the edits that occur from pPivot => pV1 (into aC1)
173222
** and pPivot => pV2 (into aC2). Each of the aC1 and aC2 arrays is
174223
** an array of integer triples. Within each triple, the first integer
175224
** is the number of lines of text to copy directly from the pivot,
@@ -269,16 +318,23 @@
269318
while( !ends_at_CPY(&aC1[i1], sz) || !ends_at_CPY(&aC2[i2], sz) ){
270319
sz++;
271320
}
272321
DEBUG( printf("CONFLICT %d\n", sz); )
273322
blob_append(pOut, mergeMarker[0], -1);
323
+ ensure_line_end(pOut, useCrLf);
274324
i1 = output_one_side(pOut, pV1, aC1, i1, sz);
325
+ ensure_line_end(pOut, useCrLf);
275326
blob_append(pOut, mergeMarker[1], -1);
327
+ ensure_line_end(pOut, useCrLf);
276328
blob_copy_lines(pOut, pPivot, sz);
329
+ ensure_line_end(pOut, useCrLf);
277330
blob_append(pOut, mergeMarker[2], -1);
331
+ ensure_line_end(pOut, useCrLf);
278332
i2 = output_one_side(pOut, pV2, aC2, i2, sz);
333
+ ensure_line_end(pOut, useCrLf);
279334
blob_append(pOut, mergeMarker[3], -1);
335
+ ensure_line_end(pOut, useCrLf);
280336
}
281337
282338
/* If we are finished with an edit triple, advance to the next
283339
** triple.
284340
*/
@@ -319,14 +375,15 @@
319375
assert( len==(int)strlen(mergeMarker[2]) );
320376
assert( len==(int)strlen(mergeMarker[3]) );
321377
assert( count(mergeMarker)==4 );
322378
for(i=0; i<n; ){
323379
for(j=0; j<4; j++){
324
- if( memcmp(&z[i], mergeMarker[j], len)==0 ) return 1;
380
+ if( (memcmp(&z[i], mergeMarker[j], len)==0)
381
+ && (i+1==n || z[i+len]=='\n' || z[i+len]=='\r') ) return 1;
325382
}
326383
while( i<n && z[i]!='\n' ){ i++; }
327
- while( i<n && z[i]=='\n' ){ i++; }
384
+ while( i<n && (z[i]=='\n' || z[i]=='\r') ){ i++; }
328385
}
329386
return 0;
330387
}
331388
332389
/*
333390
--- src/merge3.c
+++ src/merge3.c
@@ -138,16 +138,47 @@
138 /*
139 ** Text of boundary markers for merge conflicts.
140 */
141 static const char *const mergeMarker[] = {
142 /*123456789 123456789 123456789 123456789 123456789 123456789 123456789*/
143 "<<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<\n",
144 "||||||| COMMON ANCESTOR content follows ||||||||||||||||||||||||||||\n",
145 "======= MERGED IN content follows ==================================\n",
146 ">>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
147 };
148
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149
150 /*
151 ** Do a three-way merge. Initialize pOut to contain the result.
152 **
153 ** The merge is an edit against pV2. Both pV1 and pV2 have a
@@ -166,10 +197,28 @@
166 int nCpy, nDel, nIns; /* Number of lines to copy, delete, or insert */
167 int limit1, limit2; /* Sizes of aC1[] and aC2[] */
168 int nConflict = 0; /* Number of merge conflicts seen so far */
169
170 blob_zero(pOut); /* Merge results stored in pOut */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
172 /* Compute the edits that occur from pPivot => pV1 (into aC1)
173 ** and pPivot => pV2 (into aC2). Each of the aC1 and aC2 arrays is
174 ** an array of integer triples. Within each triple, the first integer
175 ** is the number of lines of text to copy directly from the pivot,
@@ -269,16 +318,23 @@
269 while( !ends_at_CPY(&aC1[i1], sz) || !ends_at_CPY(&aC2[i2], sz) ){
270 sz++;
271 }
272 DEBUG( printf("CONFLICT %d\n", sz); )
273 blob_append(pOut, mergeMarker[0], -1);
 
274 i1 = output_one_side(pOut, pV1, aC1, i1, sz);
 
275 blob_append(pOut, mergeMarker[1], -1);
 
276 blob_copy_lines(pOut, pPivot, sz);
 
277 blob_append(pOut, mergeMarker[2], -1);
 
278 i2 = output_one_side(pOut, pV2, aC2, i2, sz);
 
279 blob_append(pOut, mergeMarker[3], -1);
 
280 }
281
282 /* If we are finished with an edit triple, advance to the next
283 ** triple.
284 */
@@ -319,14 +375,15 @@
319 assert( len==(int)strlen(mergeMarker[2]) );
320 assert( len==(int)strlen(mergeMarker[3]) );
321 assert( count(mergeMarker)==4 );
322 for(i=0; i<n; ){
323 for(j=0; j<4; j++){
324 if( memcmp(&z[i], mergeMarker[j], len)==0 ) return 1;
 
325 }
326 while( i<n && z[i]!='\n' ){ i++; }
327 while( i<n && z[i]=='\n' ){ i++; }
328 }
329 return 0;
330 }
331
332 /*
333
--- src/merge3.c
+++ src/merge3.c
@@ -138,16 +138,47 @@
138 /*
139 ** Text of boundary markers for merge conflicts.
140 */
141 static const char *const mergeMarker[] = {
142 /*123456789 123456789 123456789 123456789 123456789 123456789 123456789*/
143 "<<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<",
144 "||||||| COMMON ANCESTOR content follows ||||||||||||||||||||||||||||",
145 "======= MERGED IN content follows ==================================",
146 ">>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
147 };
148
149 /*
150 ** Return true if the input blob contains any CR/LF pairs on the first
151 ** ten lines. This should be enough to detect files that use mainly CR/LF
152 ** line endings without causing a performance impact for LF only files.
153 */
154 int contains_crlf(Blob *p){
155 int i;
156 int j = 0;
157 const int maxL = 10; /* Max lines to check */
158 const char *z = blob_buffer(p);
159 int n = blob_size(p)+1;
160 for(i=1; i<n; ){
161 if( z[i-1]=='\r' && z[i]=='\n' ) return 1;
162 while( i<n && z[i]!='\n' ){ i++; }
163 j++;
164 if( j>maxL ) return 0;
165 }
166 return 0;
167 }
168
169 /*
170 ** Ensure that the text in pBlob ends with a new line.
171 ** If useCrLf is true adds "\r\n" otherwise '\n'.
172 */
173 void ensure_line_end(Blob *pBlob, int useCrLf){
174 if( pBlob->nUsed<=0 ) return;
175 if( pBlob->aData[pBlob->nUsed-1]!='\n' ){
176 if( useCrLf ) blob_append_char(pBlob, '\r');
177 blob_append_char(pBlob, '\n');
178 }
179 }
180
181 /*
182 ** Do a three-way merge. Initialize pOut to contain the result.
183 **
184 ** The merge is an edit against pV2. Both pV1 and pV2 have a
@@ -166,10 +197,28 @@
197 int nCpy, nDel, nIns; /* Number of lines to copy, delete, or insert */
198 int limit1, limit2; /* Sizes of aC1[] and aC2[] */
199 int nConflict = 0; /* Number of merge conflicts seen so far */
200
201 blob_zero(pOut); /* Merge results stored in pOut */
202
203 /* If both pV1 and pV2 start with a UTF-8 byte-order-mark (BOM),
204 ** keep it in the output. This should be secure enough not to cause
205 ** unintended changes to the merged file and consistent with what
206 ** users are using in their source files.
207 */
208 if( starts_with_utf8_bom(pV1, 0) && starts_with_utf8_bom(pV2, 0) ){
209 blob_append(pOut, (char*)get_utf8_bom(0), -1);
210 }
211
212 /* Check once to see if both pV1 and pV2 contains CR/LF endings.
213 ** If true, CR/LF pair will be used later to append the
214 ** boundary markers for merge conflicts.
215 */
216 int useCrLf = 0;
217 if( contains_crlf(pV1) && contains_crlf(pV2) ){
218 useCrLf = 1;
219 }
220
221 /* Compute the edits that occur from pPivot => pV1 (into aC1)
222 ** and pPivot => pV2 (into aC2). Each of the aC1 and aC2 arrays is
223 ** an array of integer triples. Within each triple, the first integer
224 ** is the number of lines of text to copy directly from the pivot,
@@ -269,16 +318,23 @@
318 while( !ends_at_CPY(&aC1[i1], sz) || !ends_at_CPY(&aC2[i2], sz) ){
319 sz++;
320 }
321 DEBUG( printf("CONFLICT %d\n", sz); )
322 blob_append(pOut, mergeMarker[0], -1);
323 ensure_line_end(pOut, useCrLf);
324 i1 = output_one_side(pOut, pV1, aC1, i1, sz);
325 ensure_line_end(pOut, useCrLf);
326 blob_append(pOut, mergeMarker[1], -1);
327 ensure_line_end(pOut, useCrLf);
328 blob_copy_lines(pOut, pPivot, sz);
329 ensure_line_end(pOut, useCrLf);
330 blob_append(pOut, mergeMarker[2], -1);
331 ensure_line_end(pOut, useCrLf);
332 i2 = output_one_side(pOut, pV2, aC2, i2, sz);
333 ensure_line_end(pOut, useCrLf);
334 blob_append(pOut, mergeMarker[3], -1);
335 ensure_line_end(pOut, useCrLf);
336 }
337
338 /* If we are finished with an edit triple, advance to the next
339 ** triple.
340 */
@@ -319,14 +375,15 @@
375 assert( len==(int)strlen(mergeMarker[2]) );
376 assert( len==(int)strlen(mergeMarker[3]) );
377 assert( count(mergeMarker)==4 );
378 for(i=0; i<n; ){
379 for(j=0; j<4; j++){
380 if( (memcmp(&z[i], mergeMarker[j], len)==0)
381 && (i+1==n || z[i+len]=='\n' || z[i+len]=='\r') ) return 1;
382 }
383 while( i<n && z[i]!='\n' ){ i++; }
384 while( i<n && (z[i]=='\n' || z[i]=='\r') ){ i++; }
385 }
386 return 0;
387 }
388
389 /*
390

Keyboard Shortcuts

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