@@ -109,7 +109,7 @@ static int xdl_merge_cmp_lines(xdfenv_t *xe1, int i1, xdfenv_t *xe2, int i2,
109
109
return 0 ;
110
110
}
111
111
112
- static int xdl_recs_copy_0 (int use_orig , xdfenv_t * xe , int i , int count , int add_nl , char * dest )
112
+ static int xdl_recs_copy_0 (int use_orig , xdfenv_t * xe , int i , int count , int needs_cr , int add_nl , char * dest )
113
113
{
114
114
xrecord_t * * recs ;
115
115
int size = 0 ;
@@ -125,6 +125,12 @@ static int xdl_recs_copy_0(int use_orig, xdfenv_t *xe, int i, int count, int add
125
125
if (add_nl ) {
126
126
i = recs [count - 1 ]-> size ;
127
127
if (i == 0 || recs [count - 1 ]-> ptr [i - 1 ] != '\n' ) {
128
+ if (needs_cr ) {
129
+ if (dest )
130
+ dest [size ] = '\r' ;
131
+ size ++ ;
132
+ }
133
+
128
134
if (dest )
129
135
dest [size ] = '\n' ;
130
136
size ++ ;
@@ -133,14 +139,58 @@ static int xdl_recs_copy_0(int use_orig, xdfenv_t *xe, int i, int count, int add
133
139
return size ;
134
140
}
135
141
136
- static int xdl_recs_copy (xdfenv_t * xe , int i , int count , int add_nl , char * dest )
142
+ static int xdl_recs_copy (xdfenv_t * xe , int i , int count , int needs_cr , int add_nl , char * dest )
143
+ {
144
+ return xdl_recs_copy_0 (0 , xe , i , count , needs_cr , add_nl , dest );
145
+ }
146
+
147
+ static int xdl_orig_copy (xdfenv_t * xe , int i , int count , int needs_cr , int add_nl , char * dest )
148
+ {
149
+ return xdl_recs_copy_0 (1 , xe , i , count , needs_cr , add_nl , dest );
150
+ }
151
+
152
+ /*
153
+ * Returns 1 if the i'th line ends in CR/LF (if it is the last line and
154
+ * has no eol, the preceding line, if any), 0 if it ends in LF-only, and
155
+ * -1 if the line ending cannot be determined.
156
+ */
157
+ static int is_eol_crlf (xdfile_t * file , int i )
137
158
{
138
- return xdl_recs_copy_0 (0 , xe , i , count , add_nl , dest );
159
+ long size ;
160
+
161
+ if (i < file -> nrec - 1 )
162
+ /* All lines before the last *must* end in LF */
163
+ return (size = file -> recs [i ]-> size ) > 1 &&
164
+ file -> recs [i ]-> ptr [size - 2 ] == '\r' ;
165
+ if (!file -> nrec )
166
+ /* Cannot determine eol style from empty file */
167
+ return -1 ;
168
+ if ((size = file -> recs [i ]-> size ) &&
169
+ file -> recs [i ]-> ptr [size - 1 ] == '\n' )
170
+ /* Last line; ends in LF; Is it CR/LF? */
171
+ return size > 1 &&
172
+ file -> recs [i ]-> ptr [size - 2 ] == '\r' ;
173
+ if (!i )
174
+ /* The only line has no eol */
175
+ return -1 ;
176
+ /* Determine eol from second-to-last line */
177
+ return (size = file -> recs [i - 1 ]-> size ) > 1 &&
178
+ file -> recs [i - 1 ]-> ptr [size - 2 ] == '\r' ;
139
179
}
140
180
141
- static int xdl_orig_copy (xdfenv_t * xe , int i , int count , int add_nl , char * dest )
181
+ static int is_cr_needed (xdfenv_t * xe1 , xdfenv_t * xe2 , xdmerge_t * m )
142
182
{
143
- return xdl_recs_copy_0 (1 , xe , i , count , add_nl , dest );
183
+ int needs_cr ;
184
+
185
+ /* Match post-images' preceding, or first, lines' end-of-line style */
186
+ needs_cr = is_eol_crlf (& xe1 -> xdf2 , m -> i1 ? m -> i1 - 1 : 0 );
187
+ if (needs_cr )
188
+ needs_cr = is_eol_crlf (& xe2 -> xdf2 , m -> i2 ? m -> i2 - 1 : 0 );
189
+ /* Look at pre-image's first line, unless we already settled on LF */
190
+ if (needs_cr )
191
+ needs_cr = is_eol_crlf (& xe1 -> xdf1 , 0 );
192
+ /* If still undecided, use LF-only */
193
+ return needs_cr < 0 ? 0 : needs_cr ;
144
194
}
145
195
146
196
static int fill_conflict_hunk (xdfenv_t * xe1 , const char * name1 ,
@@ -152,16 +202,17 @@ static int fill_conflict_hunk(xdfenv_t *xe1, const char *name1,
152
202
int marker1_size = (name1 ? strlen (name1 ) + 1 : 0 );
153
203
int marker2_size = (name2 ? strlen (name2 ) + 1 : 0 );
154
204
int marker3_size = (name3 ? strlen (name3 ) + 1 : 0 );
205
+ int needs_cr = is_cr_needed (xe1 , xe2 , m );
155
206
156
207
if (marker_size <= 0 )
157
208
marker_size = DEFAULT_CONFLICT_MARKER_SIZE ;
158
209
159
210
/* Before conflicting part */
160
- size += xdl_recs_copy (xe1 , i , m -> i1 - i , 0 ,
211
+ size += xdl_recs_copy (xe1 , i , m -> i1 - i , 0 , 0 ,
161
212
dest ? dest + size : NULL );
162
213
163
214
if (!dest ) {
164
- size += marker_size + 1 + marker1_size ;
215
+ size += marker_size + 1 + needs_cr + marker1_size ;
165
216
} else {
166
217
memset (dest + size , '<' , marker_size );
167
218
size += marker_size ;
@@ -170,17 +221,19 @@ static int fill_conflict_hunk(xdfenv_t *xe1, const char *name1,
170
221
memcpy (dest + size + 1 , name1 , marker1_size - 1 );
171
222
size += marker1_size ;
172
223
}
224
+ if (needs_cr )
225
+ dest [size ++ ] = '\r' ;
173
226
dest [size ++ ] = '\n' ;
174
227
}
175
228
176
229
/* Postimage from side #1 */
177
- size += xdl_recs_copy (xe1 , m -> i1 , m -> chg1 , 1 ,
230
+ size += xdl_recs_copy (xe1 , m -> i1 , m -> chg1 , needs_cr , 1 ,
178
231
dest ? dest + size : NULL );
179
232
180
233
if (style == XDL_MERGE_DIFF3 ) {
181
234
/* Shared preimage */
182
235
if (!dest ) {
183
- size += marker_size + 1 + marker3_size ;
236
+ size += marker_size + 1 + needs_cr + marker3_size ;
184
237
} else {
185
238
memset (dest + size , '|' , marker_size );
186
239
size += marker_size ;
@@ -189,25 +242,29 @@ static int fill_conflict_hunk(xdfenv_t *xe1, const char *name1,
189
242
memcpy (dest + size + 1 , name3 , marker3_size - 1 );
190
243
size += marker3_size ;
191
244
}
245
+ if (needs_cr )
246
+ dest [size ++ ] = '\r' ;
192
247
dest [size ++ ] = '\n' ;
193
248
}
194
- size += xdl_orig_copy (xe1 , m -> i0 , m -> chg0 , 1 ,
249
+ size += xdl_orig_copy (xe1 , m -> i0 , m -> chg0 , needs_cr , 1 ,
195
250
dest ? dest + size : NULL );
196
251
}
197
252
198
253
if (!dest ) {
199
- size += marker_size + 1 ;
254
+ size += marker_size + 1 + needs_cr ;
200
255
} else {
201
256
memset (dest + size , '=' , marker_size );
202
257
size += marker_size ;
258
+ if (needs_cr )
259
+ dest [size ++ ] = '\r' ;
203
260
dest [size ++ ] = '\n' ;
204
261
}
205
262
206
263
/* Postimage from side #2 */
207
- size += xdl_recs_copy (xe2 , m -> i2 , m -> chg2 , 1 ,
264
+ size += xdl_recs_copy (xe2 , m -> i2 , m -> chg2 , needs_cr , 1 ,
208
265
dest ? dest + size : NULL );
209
266
if (!dest ) {
210
- size += marker_size + 1 + marker2_size ;
267
+ size += marker_size + 1 + needs_cr + marker2_size ;
211
268
} else {
212
269
memset (dest + size , '>' , marker_size );
213
270
size += marker_size ;
@@ -216,6 +273,8 @@ static int fill_conflict_hunk(xdfenv_t *xe1, const char *name1,
216
273
memcpy (dest + size + 1 , name2 , marker2_size - 1 );
217
274
size += marker2_size ;
218
275
}
276
+ if (needs_cr )
277
+ dest [size ++ ] = '\r' ;
219
278
dest [size ++ ] = '\n' ;
220
279
}
221
280
return size ;
@@ -241,21 +300,24 @@ static int xdl_fill_merge_buffer(xdfenv_t *xe1, const char *name1,
241
300
marker_size );
242
301
else if (m -> mode & 3 ) {
243
302
/* Before conflicting part */
244
- size += xdl_recs_copy (xe1 , i , m -> i1 - i , 0 ,
303
+ size += xdl_recs_copy (xe1 , i , m -> i1 - i , 0 , 0 ,
245
304
dest ? dest + size : NULL );
246
305
/* Postimage from side #1 */
247
- if (m -> mode & 1 )
248
- size += xdl_recs_copy (xe1 , m -> i1 , m -> chg1 , (m -> mode & 2 ),
306
+ if (m -> mode & 1 ) {
307
+ int needs_cr = is_cr_needed (xe1 , xe2 , m );
308
+
309
+ size += xdl_recs_copy (xe1 , m -> i1 , m -> chg1 , needs_cr , (m -> mode & 2 ),
249
310
dest ? dest + size : NULL );
311
+ }
250
312
/* Postimage from side #2 */
251
313
if (m -> mode & 2 )
252
- size += xdl_recs_copy (xe2 , m -> i2 , m -> chg2 , 0 ,
314
+ size += xdl_recs_copy (xe2 , m -> i2 , m -> chg2 , 0 , 0 ,
253
315
dest ? dest + size : NULL );
254
316
} else
255
317
continue ;
256
318
i = m -> i1 + m -> chg1 ;
257
319
}
258
- size += xdl_recs_copy (xe1 , i , xe1 -> xdf2 .nrec - i , 0 ,
320
+ size += xdl_recs_copy (xe1 , i , xe1 -> xdf2 .nrec - i , 0 , 0 ,
259
321
dest ? dest + size : NULL );
260
322
return size ;
261
323
}
0 commit comments