137
139
* *LENGTH. The actual bytes read are stored in *LENGTH on return.
139
141
static APR_INLINE svn_error_t *
140
read_chunk(apr_file_t *file, const char *path,
142
read_chunk(apr_file_t *file,
141
143
char *buffer, apr_off_t length,
142
apr_off_t offset, apr_pool_t *pool)
144
apr_off_t offset, apr_pool_t *scratch_pool)
144
146
/* XXX: The final offset may not be the one we asked for.
147
SVN_ERR(svn_io_file_seek(file, APR_SET, &offset, pool));
149
SVN_ERR(svn_io_file_seek(file, APR_SET, &offset, scratch_pool));
148
150
return svn_io_file_read_full2(file, buffer, (apr_size_t) length,
151
NULL, NULL, scratch_pool);
287
289
length = file->chunk == last_chunk ?
288
290
offset_in_chunk(file->size) : CHUNK_SIZE;
289
SVN_ERR(read_chunk(file->file, file->path, file->buffer,
291
SVN_ERR(read_chunk(file->file, file->buffer,
290
292
length, chunk_to_offset(file->chunk),
292
294
file->endp = file->buffer + length;
314
316
/* Read previous chunk and reset pointers. */
316
SVN_ERR(read_chunk(file->file, file->path, file->buffer,
318
SVN_ERR(read_chunk(file->file, file->buffer,
317
319
CHUNK_SIZE, chunk_to_offset(file->chunk),
319
321
file->endp = file->buffer + CHUNK_SIZE;
573
574
/* There is at least more than 1 chunk,
574
575
so allocate full chunk size buffer */
575
576
file_for_suffix[i].buffer = apr_palloc(pool, CHUNK_SIZE);
576
SVN_ERR(read_chunk(file_for_suffix[i].file, file_for_suffix[i].path,
577
SVN_ERR(read_chunk(file_for_suffix[i].file,
577
578
file_for_suffix[i].buffer, length[i],
578
579
chunk_to_offset(file_for_suffix[i].chunk),
646
647
min_curp[0] += suffix_min_offset0;
648
649
/* Scan quickly by reading with machine-word granularity. */
649
for (i = 0, can_read_word = TRUE; i < file_len; i++)
650
can_read_word = can_read_word
651
&& ( (file_for_suffix[i].curp + 1
652
- sizeof(apr_uintptr_t))
650
for (i = 0, can_read_word = TRUE; can_read_word && i < file_len; i++)
651
can_read_word = ((file_for_suffix[i].curp + 1 - sizeof(apr_uintptr_t))
654
654
while (can_read_word)
656
656
apr_uintptr_t chunk;
803
801
file->size = finfo[i].size;
804
802
length[i] = finfo[i].size > CHUNK_SIZE ? CHUNK_SIZE : finfo[i].size;
805
803
file->buffer = apr_palloc(file_baton->pool, (apr_size_t) length[i]);
806
SVN_ERR(read_chunk(file->file, file->path, file->buffer,
804
SVN_ERR(read_chunk(file->file, file->buffer,
807
805
length[i], 0, file_baton->pool));
808
806
file->endp = file->buffer + length[i];
809
807
file->curp = file->buffer;
971
969
When changing things here, make sure the whitespace settings are
972
applied, or we mught not reach the exact suffix boundary as token
970
applied, or we might not reach the exact suffix boundary as token
974
SVN_ERR(read_chunk(file->file, file->path,
972
SVN_ERR(read_chunk(file->file,
976
974
chunk_to_offset(file->chunk),
977
975
file_baton->pool));
1196
1193
/* ### For compatibility; we don't support the argument to -u, because
1197
1194
* ### we don't have optional argument support. */
1198
1195
{ "unified", 'u', 0, NULL },
1196
{ "context", 'U', 1, NULL },
1199
1197
{ NULL, 0, 0, NULL }
1202
1200
svn_diff_file_options_t *
1203
1201
svn_diff_file_options_create(apr_pool_t *pool)
1205
return apr_pcalloc(pool, sizeof(svn_diff_file_options_t));
1203
svn_diff_file_options_t * opts = apr_pcalloc(pool, sizeof(*opts));
1205
opts->context_size = SVN_DIFF__UNIFIED_CONTEXT_SIZE;
1208
1210
/* A baton for use with opt_parsing_error_func(). */
1248
1250
opt_parsing_error_baton.pool = pool;
1251
memcpy((void *) (argv + 1), args->elts, sizeof(char*) * args->nelts);
1253
memcpy(argv + 1, args->elts, sizeof(char*) * args->nelts);
1252
1254
argv[args->nelts + 1] = NULL;
1254
1256
apr_getopt_init(&os, pool, args->nelts + 1, argv);
1666
1673
apr_off_t prev_context_end;
1667
1674
svn_boolean_t init_hunk = FALSE;
1669
if (original_start > SVN_DIFF__UNIFIED_CONTEXT_SIZE)
1670
context_prefix_length = SVN_DIFF__UNIFIED_CONTEXT_SIZE;
1676
if (original_start > output_baton->context_size)
1677
context_prefix_length = output_baton->context_size;
1672
1679
context_prefix_length = original_start;
1824
1831
const char *header_encoding,
1825
1832
const char *relative_to_dir,
1826
1833
svn_boolean_t show_c_function,
1835
svn_cancel_func_t cancel_func,
1827
1837
apr_pool_t *pool)
1829
1839
if (svn_diff_contains_diffs(diff))
1918
1930
original_header, modified_header,
1921
SVN_ERR(svn_diff_output(diff, &baton,
1922
&svn_diff__file_output_unified_vtable));
1933
SVN_ERR(svn_diff_output2(diff, &baton,
1934
&svn_diff__file_output_unified_vtable,
1935
cancel_func, cancel_baton));
1923
1936
SVN_ERR(output_unified_flush_hunk(&baton));
1925
1938
for (i = 0; i < 2; i++)
1940
1953
typedef struct context_saver_t {
1941
1954
svn_stream_t *stream;
1942
const char *data[SVN_DIFF__UNIFIED_CONTEXT_SIZE];
1943
apr_size_t len[SVN_DIFF__UNIFIED_CONTEXT_SIZE];
1956
const char **data; /* const char *data[context_size] */
1957
apr_size_t *len; /* apr_size_t len[context_size] */
1944
1958
apr_size_t next_slot;
1945
1959
apr_size_t total_written;
1946
1960
} context_saver_t;
1952
1966
apr_size_t *len)
1954
1968
context_saver_t *cs = baton;
1955
cs->data[cs->next_slot] = data;
1956
cs->len[cs->next_slot] = *len;
1957
cs->next_slot = (cs->next_slot + 1) % SVN_DIFF__UNIFIED_CONTEXT_SIZE;
1958
cs->total_written++;
1970
if (cs->context_size > 0)
1972
cs->data[cs->next_slot] = data;
1973
cs->len[cs->next_slot] = *len;
1974
cs->next_slot = (cs->next_slot + 1) % cs->context_size;
1975
cs->total_written++;
1959
1977
return SVN_NO_ERROR;
1999
2022
svn_stream_t *output_stream)
2002
for (i = 0; i < SVN_DIFF__UNIFIED_CONTEXT_SIZE; i++)
2025
for (i = 0; i < cs->context_size; i++)
2004
apr_size_t slot = (i + cs->next_slot) % SVN_DIFF__UNIFIED_CONTEXT_SIZE;
2027
apr_size_t slot = (i + cs->next_slot) % cs->context_size;
2005
2028
if (cs->data[slot])
2007
2030
apr_size_t len = cs->len[slot];
2023
2048
svn_stream_set_write(cs->stream, context_saver_stream_write);
2024
2049
fob->context_saver = cs;
2025
2050
fob->output_stream = cs->stream;
2051
cs->context_size = fob->context_size;
2052
cs->data = apr_pcalloc(fob->pool, sizeof(*cs->data) * cs->context_size);
2053
cs->len = apr_pcalloc(fob->pool, sizeof(*cs->len) * cs->context_size);
2029
/* A stream which prints SVN_DIFF__UNIFIED_CONTEXT_SIZE lines to
2057
/* A stream which prints LINES_TO_PRINT (based on context size) lines to
2030
2058
BATON->REAL_OUTPUT_STREAM, and then changes BATON->OUTPUT_STREAM to
2031
2059
a context_saver; used for *trailing* context. */
2061
2089
svn_pool_clear(btn->pool);
2063
2091
tcp = apr_pcalloc(btn->pool, sizeof(*tcp));
2064
tcp->lines_to_print = SVN_DIFF__UNIFIED_CONTEXT_SIZE;
2092
tcp->lines_to_print = btn->context_size;
2065
2093
tcp->fob = btn;
2066
2094
s = svn_stream_empty(btn->pool);
2067
2095
svn_stream_set_baton(s, tcp);
2191
2219
output_conflict
2222
static svn_error_t *
2223
output_conflict_with_context_marker(svn_diff3__file_output_baton_t *btn,
2229
SVN_ERR(svn_stream_printf(btn->output_stream, btn->pool,
2230
"%s (%" APR_OFF_T_FMT ")",
2233
SVN_ERR(svn_stream_printf(btn->output_stream, btn->pool,
2234
"%s (%" APR_OFF_T_FMT ",%" APR_OFF_T_FMT ")",
2235
label, start + 1, length));
2237
SVN_ERR(output_marker_eol(btn));
2239
return SVN_NO_ERROR;
2196
2242
static svn_error_t *
2197
2243
output_conflict_with_context(svn_diff3__file_output_baton_t *btn,
2206
2252
trailing context)? If so, flush it. */
2207
2253
if (btn->output_stream == btn->context_saver->stream)
2209
if (btn->context_saver->total_written > SVN_DIFF__UNIFIED_CONTEXT_SIZE)
2255
if (btn->context_saver->total_written > btn->context_size)
2210
2256
SVN_ERR(svn_stream_puts(btn->real_output_stream, "@@\n"));
2211
2257
SVN_ERR(flush_context_saver(btn->context_saver, btn->real_output_stream));
2215
2261
btn->output_stream = btn->real_output_stream;
2217
2263
/* Output the conflict itself. */
2218
SVN_ERR(svn_stream_printf(btn->output_stream, btn->pool,
2219
(modified_length == 1
2220
? "%s (%" APR_OFF_T_FMT ")"
2221
: "%s (%" APR_OFF_T_FMT ",%" APR_OFF_T_FMT ")"),
2222
btn->conflict_modified,
2223
modified_start + 1, modified_length));
2224
SVN_ERR(output_marker_eol(btn));
2264
SVN_ERR(output_conflict_with_context_marker(btn, btn->conflict_modified,
2265
modified_start, modified_length));
2225
2266
SVN_ERR(output_hunk(btn, 1/*modified*/, modified_start, modified_length));
2227
SVN_ERR(svn_stream_printf(btn->output_stream, btn->pool,
2228
(original_length == 1
2229
? "%s (%" APR_OFF_T_FMT ")"
2230
: "%s (%" APR_OFF_T_FMT ",%" APR_OFF_T_FMT ")"),
2231
btn->conflict_original,
2232
original_start + 1, original_length));
2233
SVN_ERR(output_marker_eol(btn));
2268
SVN_ERR(output_conflict_with_context_marker(btn, btn->conflict_original,
2269
original_start, original_length));
2234
2270
SVN_ERR(output_hunk(btn, 0/*original*/, original_start, original_length));
2236
2272
SVN_ERR(svn_stream_printf(btn->output_stream, btn->pool,
2237
2273
"%s%s", btn->conflict_separator, btn->marker_eol));
2238
2274
SVN_ERR(output_hunk(btn, 2/*latest*/, latest_start, latest_length));
2239
SVN_ERR(svn_stream_printf(btn->output_stream, btn->pool,
2241
? "%s (%" APR_OFF_T_FMT ")"
2242
: "%s (%" APR_OFF_T_FMT ",%" APR_OFF_T_FMT ")"),
2243
btn->conflict_latest,
2244
latest_start + 1, latest_length));
2245
SVN_ERR(output_marker_eol(btn));
2275
SVN_ERR(output_conflict_with_context_marker(btn, btn->conflict_latest,
2276
latest_start, latest_length));
2247
2278
/* Go into print-trailing-context mode instead. */
2248
2279
make_trailing_context_printer(btn);
2271
2302
if (style == svn_diff_conflict_display_resolved_modified_latest)
2274
return svn_diff_output(diff, baton,
2275
&svn_diff3__file_output_vtable);
2305
return svn_diff_output2(diff, baton,
2306
&svn_diff3__file_output_vtable,
2307
file_baton->cancel_func,
2308
file_baton->cancel_baton);
2277
2310
style = svn_diff_conflict_display_modified_latest;
2325
2358
const char *conflict_latest,
2326
2359
const char *conflict_separator,
2327
2360
svn_diff_conflict_display_style_t style,
2361
svn_cancel_func_t cancel_func,
2363
apr_pool_t *scratch_pool)
2330
2365
svn_diff3__file_output_baton_t baton;
2331
2366
apr_file_t *file[3];
2338
2373
(style == svn_diff_conflict_display_only_conflicts);
2340
2375
memset(&baton, 0, sizeof(baton));
2376
baton.context_size = SVN_DIFF__UNIFIED_CONTEXT_SIZE;
2341
2377
if (conflicts_only)
2343
baton.pool = svn_pool_create(pool);
2379
baton.pool = svn_pool_create(scratch_pool);
2344
2380
make_context_saver(&baton);
2345
2381
baton.real_output_stream = output_stream;
2351
2387
baton.path[2] = latest_path;
2352
2388
SVN_ERR(svn_utf_cstring_from_utf8(&baton.conflict_modified,
2353
2389
conflict_modified ? conflict_modified
2354
: apr_psprintf(pool, "<<<<<<< %s",
2390
: apr_psprintf(scratch_pool, "<<<<<<< %s",
2355
2391
modified_path),
2357
2393
SVN_ERR(svn_utf_cstring_from_utf8(&baton.conflict_original,
2358
2394
conflict_original ? conflict_original
2359
: apr_psprintf(pool, "||||||| %s",
2395
: apr_psprintf(scratch_pool, "||||||| %s",
2360
2396
original_path),
2362
2398
SVN_ERR(svn_utf_cstring_from_utf8(&baton.conflict_separator,
2363
2399
conflict_separator ? conflict_separator
2364
: "=======", pool));
2400
: "=======", scratch_pool));
2365
2401
SVN_ERR(svn_utf_cstring_from_utf8(&baton.conflict_latest,
2366
2402
conflict_latest ? conflict_latest
2367
: apr_psprintf(pool, ">>>>>>> %s",
2403
: apr_psprintf(scratch_pool, ">>>>>>> %s",
2371
2407
baton.conflict_style = style;
2377
2413
SVN_ERR(map_or_read_file(&file[idx],
2378
2414
MMAP_T_ARG(mm[idx])
2379
2415
&baton.buffer[idx], &size,
2380
baton.path[idx], pool));
2416
baton.path[idx], scratch_pool));
2382
2418
baton.curp[idx] = baton.buffer[idx];
2383
2419
baton.endp[idx] = baton.buffer[idx];
2395
2431
eol = APR_EOL_STR;
2396
2432
baton.marker_eol = eol;
2398
SVN_ERR(svn_diff_output(diff, &baton,
2399
&svn_diff3__file_output_vtable));
2434
baton.cancel_func = cancel_func;
2435
baton.cancel_baton = cancel_baton;
2437
SVN_ERR(svn_diff_output2(diff, &baton,
2438
&svn_diff3__file_output_vtable,
2439
cancel_func, cancel_baton));
2401
2441
for (idx = 0; idx < 3; idx++)