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

« back to all changes in this revision

Viewing changes to subversion/libsvn_diff/diff_memory.c

  • Committer: Package Import Robot
  • Author(s): James McCoy, Peter Samuelson, James McCoy
  • Date: 2014-01-12 19:48:33 UTC
  • mfrom: (0.2.10)
  • Revision ID: package-import@ubuntu.com-20140112194833-w3axfwksn296jn5x
Tags: 1.8.5-1
[ Peter Samuelson ]
* New upstream release.  (Closes: #725787) Rediff patches:
  - Remove apr-abi1 (applied upstream), rename apr-abi2 to apr-abi
  - Remove loosen-sqlite-version-check (shouldn't be needed)
  - Remove java-osgi-metadata (applied upstream)
  - svnmucc prompts for a changelog if none is provided. (Closes: #507430)
  - Remove fix-bdb-version-detection, upstream uses "apu-config --dbm-libs"
  - Remove ruby-test-wc (applied upstream)
  - Fix “svn diff -r N file” when file has svn:mime-type set.
    (Closes: #734163)
  - Support specifying an encoding for mod_dav_svn's environment in which
    hooks are run.  (Closes: #601544)
  - Fix ordering of “svnadmin dump” paths with certain APR versions.
    (Closes: #687291)
  - Provide a better error message when authentication fails with an
    svn+ssh:// URL.  (Closes: #273874)
  - Updated Polish translations.  (Closes: #690815)

[ James McCoy ]
* Remove all traces of libneon, replaced by libserf.
* patches/sqlite_3.8.x_workaround: Upstream fix for wc-queries-test test
  failurse.
* Run configure with --with-apache-libexecdir, which allows removing part of
  patches/rpath.
* Re-enable auth-test as upstream has fixed the problem of picking up
  libraries from the environment rather than the build tree.
  (Closes: #654172)
* Point LD_LIBRARY_PATH at the built auth libraries when running the svn
  command during the build.  (Closes: #678224)
* Add a NEWS entry describing how to configure mod_dav_svn to understand
  UTF-8.  (Closes: #566148)
* Remove ancient transitional package, libsvn-ruby.
* Enable compatibility with Sqlite3 versions back to Wheezy.
* Enable hardening flags.  (Closes: #734918)
* patches/build-fixes: Enable verbose build logs.
* Build against the default ruby version.  (Closes: #722393)

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
#include <apr_want.h>
28
28
#include <apr_tables.h>
29
29
 
 
30
#include <assert.h>
 
31
 
30
32
#include "svn_diff.h"
31
33
#include "svn_pools.h"
32
34
#include "svn_types.h"
35
37
#include "diff.h"
36
38
#include "svn_private_config.h"
37
39
#include "private/svn_adler32.h"
 
40
#include "private/svn_diff_private.h"
38
41
 
39
42
typedef struct source_tokens_t
40
43
{
123
126
  diff_mem_baton_t *mem_baton = baton;
124
127
  source_tokens_t *src = &(mem_baton->sources[datasource_to_index(datasource)]);
125
128
 
126
 
  if (src->tokens->nelts > src->next_token)
 
129
  if ((apr_size_t)src->tokens->nelts > src->next_token)
127
130
    {
128
131
      /* There are actually tokens to be returned */
129
132
      char *buf = mem_baton->normalization_buf[0];
341
344
{
342
345
  unified_output_context = 0,
343
346
  unified_output_delete,
344
 
  unified_output_insert
 
347
  unified_output_insert,
 
348
  unified_output_skip
345
349
} unified_output_e;
346
350
 
347
351
/* Baton for generating unified diffs */
350
354
  svn_stream_t *output_stream;
351
355
  const char *header_encoding;
352
356
  source_tokens_t sources[2]; /* 0 == original; 1 == modified */
353
 
  apr_off_t next_token; /* next token in original source */
 
357
  apr_off_t current_token[2]; /* current token per source */
354
358
 
355
359
  /* Cached markers, in header_encoding,
356
360
     indexed using unified_output_e */
363
367
  /* The delimiters of the hunk header, '@@' for text hunks and '##' for
364
368
   * property hunks. */
365
369
  const char *hunk_delimiter;
 
370
  /* The string to print after a line that does not end with a newline.
 
371
   * It must start with a '\'.  Typically "\ No newline at end of file". */
 
372
  const char *no_newline_string;
366
373
 
367
374
  /* Pool for allocation of temporary memory in the callbacks
368
375
     Should be cleared on entry of each iteration of a callback */
378
385
output_unified_token_range(output_baton_t *btn,
379
386
                           int tokens,
380
387
                           unified_output_e type,
381
 
                           apr_off_t first,
382
 
                           apr_off_t past_last)
 
388
                           apr_off_t until)
383
389
{
384
390
  source_tokens_t *source = &btn->sources[tokens];
385
 
  apr_off_t idx;
386
 
 
387
 
  past_last = (past_last > source->tokens->nelts)
388
 
    ? source->tokens->nelts : past_last;
389
 
 
390
 
  if (tokens == 0)
391
 
    /* We get context from the original source, don't expect
392
 
       to be asked to output a block which starts before
393
 
       what we already have written. */
394
 
    first = (first < btn->next_token) ? btn->next_token : first;
395
 
 
396
 
  if (first >= past_last)
 
391
 
 
392
  if (until > source->tokens->nelts)
 
393
    until = source->tokens->nelts;
 
394
 
 
395
  if (until <= btn->current_token[tokens])
397
396
    return SVN_NO_ERROR;
398
397
 
399
398
  /* Do the loop with prefix and token */
400
 
  for (idx = first; idx < past_last; idx++)
 
399
  while (TRUE)
401
400
    {
402
 
      svn_string_t *token
403
 
        = APR_ARRAY_IDX(source->tokens, idx, svn_string_t *);
404
 
      svn_stringbuf_appendcstr(btn->hunk, btn->prefix_str[type]);
405
 
      svn_stringbuf_appendbytes(btn->hunk, token->data, token->len);
 
401
      svn_string_t *token =
 
402
        APR_ARRAY_IDX(source->tokens, btn->current_token[tokens],
 
403
                      svn_string_t *);
 
404
 
 
405
      if (type != unified_output_skip)
 
406
        {
 
407
          svn_stringbuf_appendcstr(btn->hunk, btn->prefix_str[type]);
 
408
          svn_stringbuf_appendbytes(btn->hunk, token->data, token->len);
 
409
        }
406
410
 
407
411
      if (type == unified_output_context)
408
412
        {
411
415
        }
412
416
      else if (type == unified_output_delete)
413
417
        btn->hunk_length[0]++;
414
 
      else
 
418
      else if (type == unified_output_insert)
415
419
        btn->hunk_length[1]++;
416
420
 
 
421
      /* ### TODO: Add skip processing for -p handling? */
 
422
 
 
423
      btn->current_token[tokens]++;
 
424
      if (btn->current_token[tokens] == until)
 
425
        break;
417
426
    }
418
 
  if (past_last == source->tokens->nelts && source->ends_without_eol)
 
427
 
 
428
  if (btn->current_token[tokens] == source->tokens->nelts
 
429
      && source->ends_without_eol)
419
430
    {
420
431
      const char *out_str;
421
 
      SVN_ERR(svn_utf_cstring_from_utf8_ex2
422
 
              (&out_str,
423
 
               /* The string below is intentionally not marked for translation:
424
 
                  it's vital to correct operation of the diff(1)/patch(1)
425
 
                  program pair. */
426
 
               APR_EOL_STR "\\ No newline at end of file" APR_EOL_STR,
427
 
               btn->header_encoding, btn->pool));
 
432
 
 
433
      SVN_ERR(svn_utf_cstring_from_utf8_ex2(
 
434
                &out_str, btn->no_newline_string,
 
435
                btn->header_encoding, btn->pool));
428
436
      svn_stringbuf_appendcstr(btn->hunk, out_str);
429
437
    }
430
438
 
431
 
  if (tokens == 0)
432
 
    btn->next_token = past_last;
 
439
 
433
440
 
434
441
  return SVN_NO_ERROR;
435
442
}
444
451
{
445
452
  apr_off_t target_token;
446
453
  apr_size_t hunk_len;
 
454
  apr_off_t old_start;
 
455
  apr_off_t new_start;
447
456
 
448
457
  if (svn_stringbuf_isempty(baton->hunk))
449
458
    return SVN_NO_ERROR;
452
461
 
453
462
  /* Write the trailing context */
454
463
  target_token = baton->hunk_start[0] + baton->hunk_length[0]
455
 
    + SVN_DIFF__UNIFIED_CONTEXT_SIZE;
 
464
                 + SVN_DIFF__UNIFIED_CONTEXT_SIZE;
456
465
  SVN_ERR(output_unified_token_range(baton, 0 /*original*/,
457
466
                                     unified_output_context,
458
 
                                     baton->next_token, target_token));
 
467
                                     target_token));
459
468
  if (hunk_delimiter == NULL)
460
469
    hunk_delimiter = "@@";
461
470
 
 
471
  old_start = baton->hunk_start[0];
 
472
  new_start = baton->hunk_start[1];
 
473
 
 
474
  /* If the file is non-empty, convert the line indexes from
 
475
     zero based to one based */
 
476
  if (baton->hunk_length[0])
 
477
    old_start++;
 
478
  if (baton->hunk_length[1])
 
479
    new_start++;
 
480
 
462
481
  /* Write the hunk header */
463
 
  if (baton->hunk_length[0] > 0)
464
 
    /* Convert our 0-based line numbers into unidiff 1-based numbers */
465
 
    baton->hunk_start[0]++;
466
 
  SVN_ERR(svn_stream_printf_from_utf8(
467
 
            baton->output_stream, baton->header_encoding,
468
 
            baton->pool,
469
 
            /* Hunk length 1 is implied, don't show the
470
 
               length field if we have a hunk that long */
471
 
            (baton->hunk_length[0] == 1)
472
 
            ? ("%s -%" APR_OFF_T_FMT)
473
 
            : ("%s -%" APR_OFF_T_FMT ",%" APR_OFF_T_FMT),
474
 
            hunk_delimiter,
475
 
            baton->hunk_start[0], baton->hunk_length[0]));
476
 
 
477
 
  if (baton->hunk_length[1] > 0)
478
 
    /* Convert our 0-based line numbers into unidiff 1-based numbers */
479
 
    baton->hunk_start[1]++;
480
 
 
481
 
 
482
 
  /* Hunk length 1 is implied, don't show the
483
 
     length field if we have a hunk that long */
484
 
  if (baton->hunk_length[1] == 1)
485
 
    {
486
 
      SVN_ERR(svn_stream_printf_from_utf8(
487
 
                baton->output_stream, baton->header_encoding,
488
 
                baton->pool,
489
 
                " +%" APR_OFF_T_FMT " %s" APR_EOL_STR,
490
 
                baton->hunk_start[1], hunk_delimiter));
491
 
    }
492
 
  else
493
 
    {
494
 
      SVN_ERR(svn_stream_printf_from_utf8(
495
 
                baton->output_stream, baton->header_encoding,
496
 
                baton->pool,
497
 
                " +%" APR_OFF_T_FMT ",%" APR_OFF_T_FMT " %s" APR_EOL_STR,
498
 
                baton->hunk_start[1], baton->hunk_length[1],
499
 
                hunk_delimiter));
500
 
    }
 
482
  SVN_ERR(svn_diff__unified_write_hunk_header(
 
483
            baton->output_stream, baton->header_encoding, hunk_delimiter,
 
484
            old_start, baton->hunk_length[0],
 
485
            new_start, baton->hunk_length[1],
 
486
            NULL /* hunk_extra_context */,
 
487
            baton->pool));
501
488
 
502
489
  hunk_len = baton->hunk->len;
503
490
  SVN_ERR(svn_stream_write(baton->output_stream,
504
491
                           baton->hunk->data, &hunk_len));
505
492
 
506
 
  baton->hunk_length[0] = baton->hunk_length[1] = 0;
 
493
  /* Prepare for the next hunk */
 
494
  baton->hunk_length[0] = 0;
 
495
  baton->hunk_length[1] = 0;
 
496
  baton->hunk_start[0] = 0;
 
497
  baton->hunk_start[1] = 0;
507
498
  svn_stringbuf_setempty(baton->hunk);
508
499
 
509
500
  return SVN_NO_ERROR;
519
510
                             apr_off_t latest_start,
520
511
                             apr_off_t latest_length)
521
512
{
522
 
  output_baton_t *btn = baton;
523
 
  apr_off_t targ_orig, targ_mod;
524
 
 
525
 
  targ_orig = original_start - SVN_DIFF__UNIFIED_CONTEXT_SIZE;
526
 
  targ_orig = (targ_orig < 0) ? 0 : targ_orig;
527
 
  targ_mod = modified_start;
528
 
 
529
 
  /* If the changed ranges are far enough apart (no overlapping or
530
 
   * connecting context), flush the current hunk. */
531
 
  if (btn->next_token + SVN_DIFF__UNIFIED_CONTEXT_SIZE < targ_orig)
532
 
    SVN_ERR(output_unified_flush_hunk(btn, btn->hunk_delimiter));
533
 
  /* Adjust offset if it's not the first hunk. */
534
 
  else if (btn->hunk_length[0] != 0)
535
 
    targ_orig = btn->next_token;
536
 
 
537
 
  if (btn->hunk_length[0] == 0
538
 
      && btn->hunk_length[1] == 0)
539
 
    {
540
 
      btn->hunk_start[0] = targ_orig;
541
 
      btn->hunk_start[1] = targ_mod + targ_orig - original_start;
542
 
    }
543
 
 
544
 
  SVN_ERR(output_unified_token_range(btn, 0/*original*/,
545
 
                                     unified_output_context,
546
 
                                     targ_orig, original_start));
547
 
  SVN_ERR(output_unified_token_range(btn, 0/*original*/,
 
513
  output_baton_t *output_baton = baton;
 
514
  apr_off_t context_prefix_length;
 
515
  apr_off_t prev_context_end;
 
516
  svn_boolean_t init_hunk = FALSE;
 
517
 
 
518
  if (original_start > SVN_DIFF__UNIFIED_CONTEXT_SIZE)
 
519
    context_prefix_length = SVN_DIFF__UNIFIED_CONTEXT_SIZE;
 
520
  else
 
521
    context_prefix_length = original_start;
 
522
 
 
523
  /* Calculate where the previous hunk will end if we would write it now
 
524
     (including the necessary context at the end) */
 
525
  if (output_baton->hunk_length[0] > 0 || output_baton->hunk_length[1] > 0)
 
526
    {
 
527
      prev_context_end = output_baton->hunk_start[0]
 
528
                         + output_baton->hunk_length[0]
 
529
                         + SVN_DIFF__UNIFIED_CONTEXT_SIZE;
 
530
    }
 
531
  else
 
532
    {
 
533
      prev_context_end = -1;
 
534
 
 
535
      if (output_baton->hunk_start[0] == 0
 
536
          && (original_length > 0 || modified_length > 0))
 
537
        init_hunk = TRUE;
 
538
    }
 
539
 
 
540
  /* If the changed range is far enough from the previous range, flush the current
 
541
     hunk. */
 
542
  {
 
543
    apr_off_t new_hunk_start = (original_start - context_prefix_length);
 
544
 
 
545
    if (output_baton->current_token[0] < new_hunk_start
 
546
          && prev_context_end <= new_hunk_start)
 
547
      {
 
548
        SVN_ERR(output_unified_flush_hunk(output_baton,
 
549
                                          output_baton->hunk_delimiter));
 
550
        init_hunk = TRUE;
 
551
      }
 
552
    else if (output_baton->hunk_length[0] > 0
 
553
             || output_baton->hunk_length[1] > 0)
 
554
      {
 
555
        /* We extend the current hunk */
 
556
 
 
557
        /* Original: Output the context preceding the changed range */
 
558
        SVN_ERR(output_unified_token_range(output_baton, 0 /* original */,
 
559
                                           unified_output_context,
 
560
                                           original_start));
 
561
      }
 
562
  }
 
563
 
 
564
  /* Original: Skip lines until we are at the beginning of the context we want
 
565
     to display */
 
566
  SVN_ERR(output_unified_token_range(output_baton, 0 /* original */,
 
567
                                     unified_output_skip,
 
568
                                     original_start - context_prefix_length));
 
569
 
 
570
  if (init_hunk)
 
571
    {
 
572
      SVN_ERR_ASSERT(output_baton->hunk_length[0] == 0
 
573
                     && output_baton->hunk_length[1] == 0);
 
574
 
 
575
      output_baton->hunk_start[0] = original_start - context_prefix_length;
 
576
      output_baton->hunk_start[1] = modified_start - context_prefix_length;
 
577
    }
 
578
 
 
579
  /* Modified: Skip lines until we are at the start of the changed range */
 
580
  SVN_ERR(output_unified_token_range(output_baton, 1 /* modified */,
 
581
                                     unified_output_skip,
 
582
                                     modified_start));
 
583
 
 
584
  /* Original: Output the context preceding the changed range */
 
585
  SVN_ERR(output_unified_token_range(output_baton, 0 /* original */,
 
586
                                    unified_output_context,
 
587
                                    original_start));
 
588
 
 
589
  /* Both: Output the changed range */
 
590
  SVN_ERR(output_unified_token_range(output_baton, 0 /* original */,
548
591
                                     unified_output_delete,
549
 
                                     original_start,
550
592
                                     original_start + original_length));
551
 
  return output_unified_token_range(btn, 1/*modified*/, unified_output_insert,
552
 
                                    modified_start,
553
 
                                    modified_start + modified_length);
 
593
  SVN_ERR(output_unified_token_range(output_baton, 1 /* modified */,
 
594
                                     unified_output_insert,
 
595
                                     modified_start + modified_length));
 
596
 
 
597
  return SVN_NO_ERROR;
554
598
}
555
599
 
556
600
static const svn_diff_output_fns_t mem_output_unified_vtable =
584
628
      baton.output_stream = output_stream;
585
629
      baton.pool = svn_pool_create(pool);
586
630
      baton.header_encoding = header_encoding;
587
 
      baton.hunk = svn_stringbuf_create("", pool);
 
631
      baton.hunk = svn_stringbuf_create_empty(pool);
588
632
      baton.hunk_delimiter = hunk_delimiter;
 
633
      baton.no_newline_string
 
634
        = (hunk_delimiter == NULL || strcmp(hunk_delimiter, "##") != 0)
 
635
          ? APR_EOL_STR SVN_DIFF__NO_NEWLINE_AT_END_OF_FILE APR_EOL_STR
 
636
          : APR_EOL_STR SVN_DIFF__NO_NEWLINE_AT_END_OF_PROPERTY APR_EOL_STR;
589
637
 
590
638
      SVN_ERR(svn_utf_cstring_from_utf8_ex2
591
639
              (&(baton.prefix_str[unified_output_context]), " ",
602
650
 
603
651
      if (with_diff_header)
604
652
        {
605
 
          SVN_ERR(svn_stream_printf_from_utf8(output_stream,
606
 
                                              header_encoding, pool,
607
 
                                              "--- %s" APR_EOL_STR
608
 
                                              "+++ %s" APR_EOL_STR,
609
 
                                              original_header,
610
 
                                              modified_header));
 
653
          SVN_ERR(svn_diff__unidiff_write_header(
 
654
                    output_stream, header_encoding,
 
655
                    original_header, modified_header, pool));
611
656
        }
612
657
 
613
658
      SVN_ERR(svn_diff_output(diff, &baton,
680
725
 
681
726
  /* Tokenized source text */
682
727
  source_tokens_t sources[3];
683
 
  apr_off_t next_token;
 
728
  apr_off_t next_token[3];
684
729
 
685
730
  /* Markers for marking conflicted sections */
686
731
  const char *markers[4]; /* 0 = original, 1 = modified,
710
755
  int i;
711
756
  for (i = 0; i < SVN_DIFF__UNIFIED_CONTEXT_SIZE; i++)
712
757
    {
713
 
      int slot = (i + cs->next_slot) % SVN_DIFF__UNIFIED_CONTEXT_SIZE;
 
758
      apr_size_t slot = (i + cs->next_slot) % SVN_DIFF__UNIFIED_CONTEXT_SIZE;
714
759
      if (cs->data[slot])
715
760
        {
716
761
          apr_size_t len = cs->len[slot];
808
853
static svn_error_t *
809
854
output_marker_eol(merge_output_baton_t *btn)
810
855
{
811
 
  apr_size_t len = strlen(btn->marker_eol);
812
 
  return svn_stream_write(btn->output_stream, btn->marker_eol, &len);
 
856
  return svn_stream_puts(btn->output_stream, btn->marker_eol);
813
857
}
814
858
 
815
859
static svn_error_t *
816
860
output_merge_marker(merge_output_baton_t *btn, int idx)
817
861
{
818
 
  apr_size_t len = strlen(btn->markers[idx]);
819
 
  SVN_ERR(svn_stream_write(btn->output_stream, btn->markers[idx], &len));
 
862
  SVN_ERR(svn_stream_puts(btn->output_stream, btn->markers[idx]));
820
863
  return output_marker_eol(btn);
821
864
}
822
865
 
924
967
  if (btn->output_stream == btn->context_saver->stream)
925
968
    {
926
969
      if (btn->context_saver->total_written > SVN_DIFF__UNIFIED_CONTEXT_SIZE)
927
 
        SVN_ERR(svn_stream_printf(btn->real_output_stream, btn->pool, "@@\n"));
 
970
        SVN_ERR(svn_stream_puts(btn->real_output_stream, "@@\n"));
928
971
      SVN_ERR(flush_context_saver(btn->context_saver, btn->real_output_stream));
929
972
    }
930
973