Fossil SCM

Adjust 'fossil merge' command to use CR/LF line endings for conflict markings if both files being merged already use such line ending type.

marciogabe 2020-08-24 22:45 trunk
Commit 60ecf5d9ed6379968b40a1d879045655484469f81fea64a85208ce58133e68ad
1 file changed +54 -6
+54 -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,19 @@
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
+ /* Check once to see if both pV1 and pV2 contains CR/LF endings.
204
+ ** If true, CR/LF pair will be used later to append the
205
+ ** boundary markers for merge conflicts.
206
+ */
207
+ int useCrLf = 0;
208
+ if( contains_crlf(pV1) && contains_crlf(pV2) ){
209
+ useCrLf = 1;
210
+ }
171211
172212
/* Compute the edits that occur from pPivot => pV1 (into aC1)
173213
** and pPivot => pV2 (into aC2). Each of the aC1 and aC2 arrays is
174214
** an array of integer triples. Within each triple, the first integer
175215
** is the number of lines of text to copy directly from the pivot,
@@ -269,16 +309,23 @@
269309
while( !ends_at_CPY(&aC1[i1], sz) || !ends_at_CPY(&aC2[i2], sz) ){
270310
sz++;
271311
}
272312
DEBUG( printf("CONFLICT %d\n", sz); )
273313
blob_append(pOut, mergeMarker[0], -1);
314
+ ensure_line_end(pOut, useCrLf);
274315
i1 = output_one_side(pOut, pV1, aC1, i1, sz);
316
+ ensure_line_end(pOut, useCrLf);
275317
blob_append(pOut, mergeMarker[1], -1);
318
+ ensure_line_end(pOut, useCrLf);
276319
blob_copy_lines(pOut, pPivot, sz);
320
+ ensure_line_end(pOut, useCrLf);
277321
blob_append(pOut, mergeMarker[2], -1);
322
+ ensure_line_end(pOut, useCrLf);
278323
i2 = output_one_side(pOut, pV2, aC2, i2, sz);
324
+ ensure_line_end(pOut, useCrLf);
279325
blob_append(pOut, mergeMarker[3], -1);
326
+ ensure_line_end(pOut, useCrLf);
280327
}
281328
282329
/* If we are finished with an edit triple, advance to the next
283330
** triple.
284331
*/
@@ -319,14 +366,15 @@
319366
assert( len==(int)strlen(mergeMarker[2]) );
320367
assert( len==(int)strlen(mergeMarker[3]) );
321368
assert( count(mergeMarker)==4 );
322369
for(i=0; i<n; ){
323370
for(j=0; j<4; j++){
324
- if( memcmp(&z[i], mergeMarker[j], len)==0 ) return 1;
371
+ if( (memcmp(&z[i], mergeMarker[j], len)==0)
372
+ && (i+1==n || z[i+len]=='\n' || z[i+len]=='\r') ) return 1;
325373
}
326374
while( i<n && z[i]!='\n' ){ i++; }
327
- while( i<n && z[i]=='\n' ){ i++; }
375
+ while( i<n && (z[i]=='\n' || z[i]=='\r') ){ i++; }
328376
}
329377
return 0;
330378
}
331379
332380
/*
333381
--- 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,19 @@
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 +309,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 +366,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,19 @@
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 /* Check once to see if both pV1 and pV2 contains CR/LF endings.
204 ** If true, CR/LF pair will be used later to append the
205 ** boundary markers for merge conflicts.
206 */
207 int useCrLf = 0;
208 if( contains_crlf(pV1) && contains_crlf(pV2) ){
209 useCrLf = 1;
210 }
211
212 /* Compute the edits that occur from pPivot => pV1 (into aC1)
213 ** and pPivot => pV2 (into aC2). Each of the aC1 and aC2 arrays is
214 ** an array of integer triples. Within each triple, the first integer
215 ** is the number of lines of text to copy directly from the pivot,
@@ -269,16 +309,23 @@
309 while( !ends_at_CPY(&aC1[i1], sz) || !ends_at_CPY(&aC2[i2], sz) ){
310 sz++;
311 }
312 DEBUG( printf("CONFLICT %d\n", sz); )
313 blob_append(pOut, mergeMarker[0], -1);
314 ensure_line_end(pOut, useCrLf);
315 i1 = output_one_side(pOut, pV1, aC1, i1, sz);
316 ensure_line_end(pOut, useCrLf);
317 blob_append(pOut, mergeMarker[1], -1);
318 ensure_line_end(pOut, useCrLf);
319 blob_copy_lines(pOut, pPivot, sz);
320 ensure_line_end(pOut, useCrLf);
321 blob_append(pOut, mergeMarker[2], -1);
322 ensure_line_end(pOut, useCrLf);
323 i2 = output_one_side(pOut, pV2, aC2, i2, sz);
324 ensure_line_end(pOut, useCrLf);
325 blob_append(pOut, mergeMarker[3], -1);
326 ensure_line_end(pOut, useCrLf);
327 }
328
329 /* If we are finished with an edit triple, advance to the next
330 ** triple.
331 */
@@ -319,14 +366,15 @@
366 assert( len==(int)strlen(mergeMarker[2]) );
367 assert( len==(int)strlen(mergeMarker[3]) );
368 assert( count(mergeMarker)==4 );
369 for(i=0; i<n; ){
370 for(j=0; j<4; j++){
371 if( (memcmp(&z[i], mergeMarker[j], len)==0)
372 && (i+1==n || z[i+len]=='\n' || z[i+len]=='\r') ) return 1;
373 }
374 while( i<n && z[i]!='\n' ){ i++; }
375 while( i<n && (z[i]=='\n' || z[i]=='\r') ){ i++; }
376 }
377 return 0;
378 }
379
380 /*
381

Keyboard Shortcuts

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