Fossil

Check-in [bb338834]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fix -w|--ignore-all-space option such that it does exactly the same as GNU diff's option with the same name.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | strip-trailing-cr
Files: files | file ages | folders
SHA1:bb3388345d25eed7ae1dea0de629f7ee8f488ae5
User & Date: jan.nijtmans 2014-03-07 11:02:01
Context
2014-03-07
11:29
Fix some spacing issues (blame output should be exactly the same as Fossil 1.28) Make annotation work with UTF-16 files. Remove some unnecessary end-of-line spaces in text files. check-in: 4514910a user: jan.nijtmans tags: strip-trailing-cr
11:02
Fix -w|--ignore-all-space option such that it does exactly the same as GNU diff's option with the same name. check-in: bb338834 user: jan.nijtmans tags: strip-trailing-cr
09:01
Rename --ignore-space-at-eol (from Git) to -Z|--ignore-trailing-space (gnu diff). Add --ignore-all-space as well (doesn't behave exactly like GNU's option yet) check-in: d9e79f68 user: jan.nijtmans tags: strip-trailing-cr
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/diff.c.

75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
...
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
...
164
165
166
167
168
169
170
171

172
173
174

175
176
177
178
179
180
181
182
183
184





185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
...
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
...
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
...
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
...
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
....
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
....
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
....
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
....
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
....
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
** of the line.  If any line is longer than LENGTH_MASK characters,
** the file is considered binary.
*/
typedef struct DLine DLine;
struct DLine {
  const char *z;        /* The text of the line */
  unsigned int h;       /* Hash of the line */
  unsigned short indent;  /* Indent of the line. Only !=0 with --ignore-space-at sol option */
  unsigned int iNext;   /* 1+(Index of next line with same the same hash) */

  /* an array of DLine elements serves two purposes.  The fields
  ** above are one per line of input text.  But each entry is also
  ** a bucket in a hash table, as follows: */
  unsigned int iHash;   /* 1+(first entry in the hash chain) */
};
................................................................................
** Return 0 if the file is binary or contains a line that is
** too long.
**
** Profiling show that in most cases this routine consumes the bulk of
** the CPU time on a diff.
*/
static DLine *break_into_lines(const char *z, int n, int *pnLine, u64 diffFlags){
  int nLine, i, j, k, s, indent, x;
  unsigned int h, h2;
  DLine *a;

  /* Count the number of lines.  Allocate space to hold
  ** the returned array.
  */
  for(i=j=0, nLine=1; i<n; i++, j++){
................................................................................
  }

  /* Fill in the array */
  for(i=0; i<nLine; i++){
    for(j=0; z[j] && z[j]!='\n'; j++){}
    k = j;
    s = 0;
    indent = 0;

    if( diffFlags & DIFF_IGNORE_EOLWS ){
      while( k>0 && fossil_isspace(z[k-1]) ){ k--; }
    }else if( diffFlags & DIFF_STRIP_EOLCR ){

      if( k>0 && z[k-1]=='\r' ){ k--; }
    }
    if( (diffFlags & DIFF_IGNORE_ALLWS)==DIFF_IGNORE_ALLWS ){
      while( s<k && fossil_isspace(z[s]) ){
        if( z[s]=='\t' ){
          indent = ((indent+9)/8)*8;
        }else if( z[s]==' ' ){
          indent++;
        }
        s++;





      }
    }
    a[i].z = z+s;
    a[i].indent = s;
    for(h=0, x=s; x<k; x++){
      h = h ^ (h<<2) ^ z[x];
    }
    a[i].h = h = (h<<LENGTH_MASK_SZ) | (k-s);
    h2 = h % nLine;
    a[i].iNext = a[h2].iHash;
    a[h2].iHash = i+1;
    z += j+1;
  }

  /* Return results */
................................................................................
    if( pRe && re_dline_match(pRe, pLine, 1)==0 ){
      cPrefix = ' ';
    }else if( cPrefix=='+' ){
      blob_append(pOut, "<span class=\"diffadd\">", -1);
    }else if( cPrefix=='-' ){
      blob_append(pOut, "<span class=\"diffrm\">", -1);
    }
    if( pLine->indent ){
      blob_appendf(pOut, "%*s", pLine->indent, " ");
    }
    htmlize_to_blob(pOut, pLine->z, (pLine->h & LENGTH_MASK));
    if( cPrefix!=' ' ){
      blob_append(pOut, "</span>", -1);
    }
  }else{
    if( pLine->indent ){
      blob_appendf(pOut, "%*s", pLine->indent, " ");
    }
    blob_append(pOut, pLine->z, pLine->h & LENGTH_MASK);
  }
  blob_append(pOut, "\n", 1);
}

/*
** Add two line numbers to the beginning of an output line for a context
** diff.  One or the other of the two numbers might be zero, which means
................................................................................
** rendering to width bytes if col is SBS_TXTA and escHtml is false.
**
** This comment contains multibyte unicode characters (ü, Æ, ð) in order
** to test the ability of the diff code to handle such characters.
*/
static void sbsWriteText(SbsLine *p, DLine *pLine, int col){
  Blob *pCol = p->apCols[col];
  int n = pLine->h & LENGTH_MASK;
  int i;   /* Number of input characters consumed */
  int k;   /* Cursor position */
  int needEndSpan = 0;
  const char *zIn = pLine->z;
  int w = p->width;
  int colorize = p->escHtml;
  if( colorize && p->pRe && re_dline_match(p->pRe, pLine, 1)==0 ){
................................................................................
        needEndSpan = 0;
        if( p->iEnd2 ){
          p->iEnd = p->iEnd2;
          p->iEnd2 = 0;
        }
      }
    }
    if( pLine->indent && i==0 ){
      blob_appendf(pCol, "%*s", pLine->indent, " ");
    }
    if( c=='\t' && !p->escHtml ){
      blob_append(pCol, " ", 1);
      while( (k&7)!=7 && (p->escHtml || k<w) ){
        blob_append(pCol, " ", 1);
        k++;
      }
    }else if( c=='\r' || c=='\f' ){
................................................................................
  }
  if( needEndSpan ){
    blob_append(pCol, "</span>", 7);
  }
  if( col==SBS_TXTB ){
    sbsWriteNewlines(p);
  }else if( !p->escHtml ){
    sbsWriteSpace(p, w-k-pLine->indent, SBS_TXTA);
  }
}

/*
** Append a column to the final output blob.
*/
static void sbsWriteColumn(Blob *pOut, Blob *pCol, int col){
................................................................................
** of the following structure.
*/
typedef struct Annotator Annotator;
struct Annotator {
  DContext c;       /* The diff-engine context */
  struct AnnLine {  /* Lines of the original files... */
    const char *z;       /* The text of the line */
    short int n;         /* Number of bytes. Whether this omits sol/eol spacing
                            depends on the diffFlags) */
    unsigned short indent; /* Indenting (number of initial spaces, only used
                              if sol-spacing is ignored in the diffFlags) */
    short int iVers;     /* Level at which tag was set */
  } *aOrig;
  int nOrig;        /* Number of elements in aOrig[] */
  int nVers;        /* Number of versions analyzed */
  int bLimit;       /* True if the iLimit was reached */
  struct AnnVers {
    const char *zFUuid;   /* File being analyzed */
................................................................................
                              diffFlags);
  if( p->c.aTo==0 ){
    return 1;
  }
  p->aOrig = fossil_malloc( sizeof(p->aOrig[0])*p->c.nTo );
  for(i=0; i<p->c.nTo; i++){
    p->aOrig[i].z = p->c.aTo[i].z;
    p->aOrig[i].n = p->c.aTo[i].h & LENGTH_MASK;
    p->aOrig[i].indent = p->c.aTo[i].indent;
    p->aOrig[i].iVers = -1;
  }
  p->nOrig = p->c.nTo;
  return 0;
}

/*
................................................................................
    @ from check-in %z(href("%R/info/%S",zCI))%S(zCI)</a>:</h2>
  }
  @ <pre>
  for(i=0; i<ann.nOrig; i++){
    int iVers = ann.aOrig[i].iVers;
    char *z = (char*)ann.aOrig[i].z;
    int n = ann.aOrig[i].n;
    int indent = ann.aOrig[i].indent+1;
    char zPrefix[300];
    z[n] = 0;
    if( iLimit>ann.nVers && iVers<0 ) iVers = ann.nVers-1;

    if( bBlame ){
      if( iVers>=0 ){
        struct AnnVers *p = ann.aVers+iVers;
................................................................................
        char *zLink = xhref("target='infowindow'", "%R/info/%S", p->zMUuid);
        sqlite3_snprintf(sizeof(zPrefix), zPrefix,
             "<span style='background-color:%s'>"
             "%s%.10s</a> %s</span> %13.13s:",
             p->zBgColor, zLink, p->zMUuid, p->zDate, p->zUser);
        fossil_free(zLink);
      }else{
        sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%36s%*s", indent, " ");
      }
    }else{
      if( iVers>=0 ){
        struct AnnVers *p = ann.aVers+iVers;
        char *zLink = xhref("target='infowindow'", "%R/info/%S", p->zMUuid);
        sqlite3_snprintf(sizeof(zPrefix), zPrefix,
             "<span style='background-color:%s'>"
             "%s%.10s</a> %s</span> %4d:%*s",
             p->zBgColor, zLink, p->zMUuid, p->zDate, i+1, indent, " ");
        fossil_free(zLink);
      }else{
        sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%22s%4d:%*s", "", i+1, indent, " ");
      }
    }
    @ %s(zPrefix)%h(z)

  }
  @ </pre>
  style_footer();
................................................................................
                   i+1, p->zDate, p->zMUuid, p->zFUuid);
    }
    fossil_print("---------------------------------------------------\n");
  }
  for(i=0; i<ann.nOrig; i++){
    int iVers = ann.aOrig[i].iVers;
    char *z = (char*)ann.aOrig[i].z;
    int indent = ann.aOrig[i].indent + 1;
    int n = ann.aOrig[i].n;
    struct AnnVers *p;
    if( iLimit>ann.nVers && iVers<0 ) iVers = ann.nVers-1;
    p = ann.aVers + iVers;
    if( bBlame ){
      if( iVers>=0 ){
        fossil_print("%.10s %s %13.13s:%*s%.*s\n",
             fileVers ? p->zFUuid : p->zMUuid, p->zDate, p->zUser, indent, " ", n, z);
      }else{
        fossil_print("%35s %*s%.*s\n", "", indent, " ", n, z);
      }
    }else{
      if( iVers>=0 ){
        fossil_print("%.10s %s %5d:%*s%.*s\n",
             fileVers ? p->zFUuid : p->zMUuid, p->zDate, i+1, indent, " ", n, z);
      }else{
        fossil_print("%21s %5d:%*s%.*s\n",
             "", i+1, indent, " ", n, z);
      }
    }
  }
}







|







 







|







 







|
>

|

>



|
<
<
<
<
|
<
>
>
>
>
>


|
|
<
<
<
|







 







<
<
<





<
<
<
|







 







|







 







<
<
<







 







|







 







|
<
<
<







 







|
<







 







<







 







|







|
|


|







 







<






|
|

|



|
|
|
|
|




75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
...
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
...
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180




181

182
183
184
185
186
187
188
189
190



191
192
193
194
195
196
197
198
...
240
241
242
243
244
245
246



247
248
249
250
251



252
253
254
255
256
257
258
259
...
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
...
526
527
528
529
530
531
532



533
534
535
536
537
538
539
...
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
....
1968
1969
1970
1971
1972
1973
1974
1975



1976
1977
1978
1979
1980
1981
1982
....
2002
2003
2004
2005
2006
2007
2008
2009

2010
2011
2012
2013
2014
2015
2016
....
2309
2310
2311
2312
2313
2314
2315

2316
2317
2318
2319
2320
2321
2322
....
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
....
2431
2432
2433
2434
2435
2436
2437

2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
** of the line.  If any line is longer than LENGTH_MASK characters,
** the file is considered binary.
*/
typedef struct DLine DLine;
struct DLine {
  const char *z;        /* The text of the line */
  unsigned int h;       /* Hash of the line */
  unsigned short extent;  /* Extent of the line. how much longer than recorded in h */
  unsigned int iNext;   /* 1+(Index of next line with same the same hash) */

  /* an array of DLine elements serves two purposes.  The fields
  ** above are one per line of input text.  But each entry is also
  ** a bucket in a hash table, as follows: */
  unsigned int iHash;   /* 1+(first entry in the hash chain) */
};
................................................................................
** Return 0 if the file is binary or contains a line that is
** too long.
**
** Profiling show that in most cases this routine consumes the bulk of
** the CPU time on a diff.
*/
static DLine *break_into_lines(const char *z, int n, int *pnLine, u64 diffFlags){
  int nLine, i, j, k, s, extent, x, numws;
  unsigned int h, h2;
  DLine *a;

  /* Count the number of lines.  Allocate space to hold
  ** the returned array.
  */
  for(i=j=0, nLine=1; i<n; i++, j++){
................................................................................
  }

  /* Fill in the array */
  for(i=0; i<nLine; i++){
    for(j=0; z[j] && z[j]!='\n'; j++){}
    k = j;
    s = 0;
    extent = 0; /* number of spaces ignored from start/end */
    numws = 0; /* number of spaces ignored in between */
    if( diffFlags & DIFF_IGNORE_EOLWS ){
      while( k>0 && fossil_isspace(z[k-1]) ){ k--; extent++;}
    }else if( diffFlags & DIFF_STRIP_EOLCR ){
      /* Don't do "extend++" here, because the CR needs to be stripped! */
      if( k>0 && z[k-1]=='\r' ){ k--; }
    }
    if( (diffFlags & DIFF_IGNORE_ALLWS)==DIFF_IGNORE_ALLWS ){
      while( s<k && fossil_isspace(z[s]) ){s++; extent++;}




    }

    for(h=0, x=s; x<k; x++){
      if( (diffFlags & DIFF_IGNORE_ALLWS)==DIFF_IGNORE_ALLWS && fossil_isspace(z[x]) ){
        ++numws;
      }else{
        h = h ^ (h<<2) ^ z[x];
      }
    }
    a[i].z = z;
    a[i].extent = extent+numws;



    a[i].h = h = (h<<LENGTH_MASK_SZ) | (k-s-numws);
    h2 = h % nLine;
    a[i].iNext = a[h2].iHash;
    a[h2].iHash = i+1;
    z += j+1;
  }

  /* Return results */
................................................................................
    if( pRe && re_dline_match(pRe, pLine, 1)==0 ){
      cPrefix = ' ';
    }else if( cPrefix=='+' ){
      blob_append(pOut, "<span class=\"diffadd\">", -1);
    }else if( cPrefix=='-' ){
      blob_append(pOut, "<span class=\"diffrm\">", -1);
    }



    htmlize_to_blob(pOut, pLine->z, (pLine->h & LENGTH_MASK));
    if( cPrefix!=' ' ){
      blob_append(pOut, "</span>", -1);
    }
  }else{



    blob_append(pOut, pLine->z, (pLine->h & LENGTH_MASK) + pLine->extent);
  }
  blob_append(pOut, "\n", 1);
}

/*
** Add two line numbers to the beginning of an output line for a context
** diff.  One or the other of the two numbers might be zero, which means
................................................................................
** rendering to width bytes if col is SBS_TXTA and escHtml is false.
**
** This comment contains multibyte unicode characters (ü, Æ, ð) in order
** to test the ability of the diff code to handle such characters.
*/
static void sbsWriteText(SbsLine *p, DLine *pLine, int col){
  Blob *pCol = p->apCols[col];
  int n = (pLine->h & LENGTH_MASK) + pLine->extent;
  int i;   /* Number of input characters consumed */
  int k;   /* Cursor position */
  int needEndSpan = 0;
  const char *zIn = pLine->z;
  int w = p->width;
  int colorize = p->escHtml;
  if( colorize && p->pRe && re_dline_match(p->pRe, pLine, 1)==0 ){
................................................................................
        needEndSpan = 0;
        if( p->iEnd2 ){
          p->iEnd = p->iEnd2;
          p->iEnd2 = 0;
        }
      }
    }



    if( c=='\t' && !p->escHtml ){
      blob_append(pCol, " ", 1);
      while( (k&7)!=7 && (p->escHtml || k<w) ){
        blob_append(pCol, " ", 1);
        k++;
      }
    }else if( c=='\r' || c=='\f' ){
................................................................................
  }
  if( needEndSpan ){
    blob_append(pCol, "</span>", 7);
  }
  if( col==SBS_TXTB ){
    sbsWriteNewlines(p);
  }else if( !p->escHtml ){
    sbsWriteSpace(p, w-k, SBS_TXTA);
  }
}

/*
** Append a column to the final output blob.
*/
static void sbsWriteColumn(Blob *pOut, Blob *pCol, int col){
................................................................................
** of the following structure.
*/
typedef struct Annotator Annotator;
struct Annotator {
  DContext c;       /* The diff-engine context */
  struct AnnLine {  /* Lines of the original files... */
    const char *z;       /* The text of the line */
    short int n;         /* Number of bytes */



    short int iVers;     /* Level at which tag was set */
  } *aOrig;
  int nOrig;        /* Number of elements in aOrig[] */
  int nVers;        /* Number of versions analyzed */
  int bLimit;       /* True if the iLimit was reached */
  struct AnnVers {
    const char *zFUuid;   /* File being analyzed */
................................................................................
                              diffFlags);
  if( p->c.aTo==0 ){
    return 1;
  }
  p->aOrig = fossil_malloc( sizeof(p->aOrig[0])*p->c.nTo );
  for(i=0; i<p->c.nTo; i++){
    p->aOrig[i].z = p->c.aTo[i].z;
    p->aOrig[i].n = (p->c.aTo[i].h & LENGTH_MASK) + p->c.aTo[i].extent;

    p->aOrig[i].iVers = -1;
  }
  p->nOrig = p->c.nTo;
  return 0;
}

/*
................................................................................
    @ from check-in %z(href("%R/info/%S",zCI))%S(zCI)</a>:</h2>
  }
  @ <pre>
  for(i=0; i<ann.nOrig; i++){
    int iVers = ann.aOrig[i].iVers;
    char *z = (char*)ann.aOrig[i].z;
    int n = ann.aOrig[i].n;

    char zPrefix[300];
    z[n] = 0;
    if( iLimit>ann.nVers && iVers<0 ) iVers = ann.nVers-1;

    if( bBlame ){
      if( iVers>=0 ){
        struct AnnVers *p = ann.aVers+iVers;
................................................................................
        char *zLink = xhref("target='infowindow'", "%R/info/%S", p->zMUuid);
        sqlite3_snprintf(sizeof(zPrefix), zPrefix,
             "<span style='background-color:%s'>"
             "%s%.10s</a> %s</span> %13.13s:",
             p->zBgColor, zLink, p->zMUuid, p->zDate, p->zUser);
        fossil_free(zLink);
      }else{
        sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%36s ", "");
      }
    }else{
      if( iVers>=0 ){
        struct AnnVers *p = ann.aVers+iVers;
        char *zLink = xhref("target='infowindow'", "%R/info/%S", p->zMUuid);
        sqlite3_snprintf(sizeof(zPrefix), zPrefix,
             "<span style='background-color:%s'>"
             "%s%.10s</a> %s</span> %4d: ",
             p->zBgColor, zLink, p->zMUuid, p->zDate, i+1);
        fossil_free(zLink);
      }else{
        sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%22s%4d: ", "", i+1);
      }
    }
    @ %s(zPrefix)%h(z)

  }
  @ </pre>
  style_footer();
................................................................................
                   i+1, p->zDate, p->zMUuid, p->zFUuid);
    }
    fossil_print("---------------------------------------------------\n");
  }
  for(i=0; i<ann.nOrig; i++){
    int iVers = ann.aOrig[i].iVers;
    char *z = (char*)ann.aOrig[i].z;

    int n = ann.aOrig[i].n;
    struct AnnVers *p;
    if( iLimit>ann.nVers && iVers<0 ) iVers = ann.nVers-1;
    p = ann.aVers + iVers;
    if( bBlame ){
      if( iVers>=0 ){
        fossil_print("%.10s %s %13.13s: %.*s\n",
             fileVers ? p->zFUuid : p->zMUuid, p->zDate, p->zUser, n, z);
      }else{
        fossil_print("%35s  %.*s\n", "", n, z);
      }
    }else{
      if( iVers>=0 ){
        fossil_print("%.10s %s %5d: %.*s\n",
             fileVers ? p->zFUuid : p->zMUuid, p->zDate, i+1, n, z);
      }else {
        fossil_print("%21s %5d: %.*s\n",
             "", i+1, n, z);
      }
    }
  }
}