~ubuntu-branches/debian/sid/subversion/sid

« back to all changes in this revision

Viewing changes to subversion/libsvn_diff/diff_file.c

  • Committer: Package Import Robot
  • Author(s): James McCoy
  • Date: 2015-08-07 21:32:47 UTC
  • mfrom: (0.2.15) (4.1.7 experimental)
  • Revision ID: package-import@ubuntu.com-20150807213247-ozyewtmgsr6tkewl
Tags: 1.9.0-1
* Upload to unstable
* New upstream release.
  + Security fixes
    - CVE-2015-3184: Mixed anonymous/authenticated path-based authz with
      httpd 2.4
    - CVE-2015-3187: svn_repos_trace_node_locations() reveals paths hidden
      by authz
* Add >= 2.7 requirement for python-all-dev Build-Depends, needed to run
  tests.
* Remove Build-Conflicts against ruby-test-unit.  (Closes: #791844)
* Remove patches/apache_module_dependency in favor of expressing the
  dependencies in authz_svn.load/dav_svn.load.
* Build-Depend on apache2-dev (>= 2.4.16) to ensure ap_some_authn_required()
  is available when building mod_authz_svn and Depend on apache2-bin (>=
  2.4.16) for runtime support.

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
#include <apr_mmap.h>
32
32
#include <apr_getopt.h>
33
33
 
 
34
#include <assert.h>
 
35
 
34
36
#include "svn_error.h"
35
37
#include "svn_diff.h"
36
38
#include "svn_types.h"
137
139
 * *LENGTH.  The actual bytes read are stored in *LENGTH on return.
138
140
 */
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)
143
145
{
144
146
  /* XXX: The final offset may not be the one we asked for.
145
147
   * XXX: Check.
146
148
   */
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,
149
 
                                NULL, NULL, pool);
 
151
                                NULL, NULL, scratch_pool);
150
152
}
151
153
 
152
154
 
286
288
      file->chunk++;
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),
291
293
                         pool));
292
294
      file->endp = file->buffer + length;
313
315
    {
314
316
      /* Read previous chunk and reset pointers. */
315
317
      file->chunk--;
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),
318
320
                         pool));
319
321
      file->endp = file->buffer + CHUNK_SIZE;
542
544
  int suffix_lines_to_keep = SUFFIX_LINES_TO_KEEP;
543
545
  svn_boolean_t is_match;
544
546
  apr_off_t lines = 0;
545
 
  svn_boolean_t had_cr;
546
547
  svn_boolean_t had_nl;
547
548
  apr_size_t i;
548
549
 
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),
579
580
                             pool));
646
647
        min_curp[0] += suffix_min_offset0;
647
648
 
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))
653
 
                            > min_curp[i]);
 
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))
 
652
                         > min_curp[i]);
 
653
 
654
654
      while (can_read_word)
655
655
        {
656
656
          apr_uintptr_t chunk;
664
664
          if (contains_eol(chunk))
665
665
            break;
666
666
 
667
 
          for (i = 1, is_match = TRUE; i < file_len; i++)
668
 
            is_match = is_match
669
 
                       && (   chunk
 
667
          for (i = 1, is_match = TRUE; is_match && i < file_len; i++)
 
668
            is_match = (chunk
670
669
                           == *(const apr_uintptr_t *)
671
670
                                    (file_for_suffix[i].curp + 1
672
671
                                       - sizeof(apr_uintptr_t)));
685
684
 
686
685
          /* We skipped some bytes, so there are no closing EOLs */
687
686
          had_nl = FALSE;
688
 
          had_cr = FALSE;
689
687
        }
690
688
 
691
689
      /* The > min_curp[i] check leaves at least one final byte for checking
712
710
     one file reaches its end. */
713
711
  do
714
712
    {
715
 
      had_cr = FALSE;
 
713
      svn_boolean_t had_cr = FALSE;
716
714
      while (!is_one_at_eof(file_for_suffix, file_len)
717
715
             && *file_for_suffix[0].curp != '\n'
718
716
             && *file_for_suffix[0].curp != '\r')
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;
969
967
         function.
970
968
 
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
973
971
         boundary. */
974
 
      SVN_ERR(read_chunk(file->file, file->path,
 
972
      SVN_ERR(read_chunk(file->file,
975
973
                         curp, length,
976
974
                         chunk_to_offset(file->chunk),
977
975
                         file_baton->pool));
1113
1111
                COMPARE_CHUNK_SIZE : raw_length[i];
1114
1112
 
1115
1113
              SVN_ERR(read_chunk(file[i]->file,
1116
 
                                 file[i]->path,
1117
1114
                                 bufp[i], length[i], offset[i],
1118
1115
                                 file_baton->pool));
1119
1116
              offset[i] += length[i];
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 }
1200
1198
};
1201
1199
 
1202
1200
svn_diff_file_options_t *
1203
1201
svn_diff_file_options_create(apr_pool_t *pool)
1204
1202
{
1205
 
  return apr_pcalloc(pool, sizeof(svn_diff_file_options_t));
 
1203
  svn_diff_file_options_t * opts = apr_pcalloc(pool, sizeof(*opts));
 
1204
 
 
1205
  opts->context_size = SVN_DIFF__UNIFIED_CONTEXT_SIZE;
 
1206
 
 
1207
  return opts;
1206
1208
}
1207
1209
 
1208
1210
/* A baton for use with opt_parsing_error_func(). */
1248
1250
  opt_parsing_error_baton.pool = pool;
1249
1251
 
1250
1252
  argv[0] = "";
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;
1253
1255
 
1254
1256
  apr_getopt_init(&os, pool, args->nelts + 1, argv);
1291
1293
        case 'p':
1292
1294
          options->show_c_function = TRUE;
1293
1295
          break;
 
1296
        case 'U':
 
1297
          SVN_ERR(svn_cstring_atoi(&options->context_size, opt_arg));
 
1298
          break;
1294
1299
        default:
1295
1300
          break;
1296
1301
        }
1410
1415
  /* Extra context for the current hunk. */
1411
1416
  char hunk_extra_context[SVN_DIFF__EXTRA_CONTEXT_LENGTH + 1];
1412
1417
 
 
1418
  int context_size;
 
1419
 
1413
1420
  apr_pool_t *pool;
1414
1421
} svn_diff__file_output_baton_t;
1415
1422
 
1615
1622
    }
1616
1623
 
1617
1624
  target_line = baton->hunk_start[0] + baton->hunk_length[0]
1618
 
                + SVN_DIFF__UNIFIED_CONTEXT_SIZE;
 
1625
                + baton->context_size;
1619
1626
 
1620
1627
  /* Add trailing context to the hunk */
1621
1628
  SVN_ERR(output_unified_diff_range(baton, 0 /* original */,
1666
1673
  apr_off_t prev_context_end;
1667
1674
  svn_boolean_t init_hunk = FALSE;
1668
1675
 
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;
1671
1678
  else
1672
1679
    context_prefix_length = original_start;
1673
1680
 
1677
1684
    {
1678
1685
      prev_context_end = output_baton->hunk_start[0]
1679
1686
                         + output_baton->hunk_length[0]
1680
 
                         + SVN_DIFF__UNIFIED_CONTEXT_SIZE;
 
1687
                         + output_baton->context_size;
1681
1688
    }
1682
1689
  else
1683
1690
    {
1815
1822
};
1816
1823
 
1817
1824
svn_error_t *
1818
 
svn_diff_file_output_unified3(svn_stream_t *output_stream,
 
1825
svn_diff_file_output_unified4(svn_stream_t *output_stream,
1819
1826
                              svn_diff_t *diff,
1820
1827
                              const char *original_path,
1821
1828
                              const char *modified_path,
1824
1831
                              const char *header_encoding,
1825
1832
                              const char *relative_to_dir,
1826
1833
                              svn_boolean_t show_c_function,
 
1834
                              int context_size,
 
1835
                              svn_cancel_func_t cancel_func,
 
1836
                              void *cancel_baton,
1827
1837
                              apr_pool_t *pool)
1828
1838
{
1829
1839
  if (svn_diff_contains_diffs(diff))
1840
1850
      baton.hunk = svn_stringbuf_create_empty(pool);
1841
1851
      baton.show_c_function = show_c_function;
1842
1852
      baton.extra_context = svn_stringbuf_create_empty(pool);
 
1853
      baton.context_size = (context_size >= 0) ? context_size
 
1854
                                              : SVN_DIFF__UNIFIED_CONTEXT_SIZE;
1843
1855
 
1844
1856
      if (show_c_function)
1845
1857
        {
1918
1930
                                             original_header, modified_header,
1919
1931
                                             pool));
1920
1932
 
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));
1924
1937
 
1925
1938
      for (i = 0; i < 2; i++)
1939
1952
   *pointers! */
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];
 
1955
  int 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)
1953
1967
{
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++;
 
1969
 
 
1970
  if (cs->context_size > 0)
 
1971
    {
 
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++;
 
1976
    }
1959
1977
  return SVN_NO_ERROR;
1960
1978
}
1961
1979
 
1980
1998
  const char *marker_eol;
1981
1999
 
1982
2000
  svn_diff_conflict_display_style_t conflict_style;
 
2001
  int context_size;
 
2002
 
 
2003
  /* cancel support */
 
2004
  svn_cancel_func_t cancel_func;
 
2005
  void *cancel_baton;
1983
2006
 
1984
2007
  /* The rest of the fields are for
1985
2008
     svn_diff_conflict_display_only_conflicts only.  Note that for
1999
2022
                    svn_stream_t *output_stream)
2000
2023
{
2001
2024
  int i;
2002
 
  for (i = 0; i < SVN_DIFF__UNIFIED_CONTEXT_SIZE; i++)
 
2025
  for (i = 0; i < cs->context_size; i++)
2003
2026
    {
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])
2006
2029
        {
2007
2030
          apr_size_t len = cs->len[slot];
2016
2039
{
2017
2040
  context_saver_t *cs;
2018
2041
 
 
2042
  assert(fob->context_size > 0); /* Or nothing to save */
 
2043
 
2019
2044
  svn_pool_clear(fob->pool);
2020
2045
  cs = apr_pcalloc(fob->pool, sizeof(*cs));
2021
2046
  cs->stream = svn_stream_empty(fob->pool);
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);
2026
2054
}
2027
2055
 
2028
2056
 
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. */
2032
2060
 
2061
2089
  svn_pool_clear(btn->pool);
2062
2090
 
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
2192
2220
};
2193
2221
 
2194
 
 
 
2222
static svn_error_t *
 
2223
output_conflict_with_context_marker(svn_diff3__file_output_baton_t *btn,
 
2224
                                    const char *label,
 
2225
                                    apr_off_t start,
 
2226
                                    apr_off_t length)
 
2227
{
 
2228
  if (length == 1)
 
2229
    SVN_ERR(svn_stream_printf(btn->output_stream, btn->pool,
 
2230
                              "%s (%" APR_OFF_T_FMT ")",
 
2231
                              label, start + 1));
 
2232
  else
 
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));
 
2236
 
 
2237
  SVN_ERR(output_marker_eol(btn));
 
2238
 
 
2239
  return SVN_NO_ERROR;
 
2240
}
2195
2241
 
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)
2208
2254
    {
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));
2212
2258
    }
2215
2261
  btn->output_stream = btn->real_output_stream;
2216
2262
 
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));
2226
2267
 
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));
2235
2271
 
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,
2240
 
                            (latest_length == 1
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));
2246
2277
 
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)
2272
2303
    {
2273
2304
      if (diff)
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);
2276
2309
      else
2277
2310
        style = svn_diff_conflict_display_modified_latest;
2278
2311
    }
2315
2348
}
2316
2349
 
2317
2350
svn_error_t *
2318
 
svn_diff_file_output_merge2(svn_stream_t *output_stream,
 
2351
svn_diff_file_output_merge3(svn_stream_t *output_stream,
2319
2352
                            svn_diff_t *diff,
2320
2353
                            const char *original_path,
2321
2354
                            const char *modified_path,
2325
2358
                            const char *conflict_latest,
2326
2359
                            const char *conflict_separator,
2327
2360
                            svn_diff_conflict_display_style_t style,
2328
 
                            apr_pool_t *pool)
 
2361
                            svn_cancel_func_t cancel_func,
 
2362
                            void *cancel_baton,
 
2363
                            apr_pool_t *scratch_pool)
2329
2364
{
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);
2339
2374
 
2340
2375
  memset(&baton, 0, sizeof(baton));
 
2376
  baton.context_size = SVN_DIFF__UNIFIED_CONTEXT_SIZE;
2341
2377
  if (conflicts_only)
2342
2378
    {
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;
2346
2382
    }
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),
2356
 
                                    pool));
 
2392
                                    scratch_pool));
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),
2361
 
                                    pool));
 
2397
                                    scratch_pool));
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",
2368
2404
                                                   latest_path),
2369
 
                                    pool));
 
2405
                                    scratch_pool));
2370
2406
 
2371
2407
  baton.conflict_style = style;
2372
2408
 
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));
2381
2417
 
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;
2397
2433
 
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;
 
2436
 
 
2437
  SVN_ERR(svn_diff_output2(diff, &baton,
 
2438
                          &svn_diff3__file_output_vtable,
 
2439
                          cancel_func, cancel_baton));
2400
2440
 
2401
2441
  for (idx = 0; idx < 3; idx++)
2402
2442
    {
2414
2454
 
2415
2455
      if (file[idx])
2416
2456
        {
2417
 
          SVN_ERR(svn_io_file_close(file[idx], pool));
 
2457
          SVN_ERR(svn_io_file_close(file[idx], scratch_pool));
2418
2458
        }
2419
2459
    }
2420
2460