Fossil

Check-in [a5e9410f]
Login

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

Overview
Comment:undo [b9227b85cb|status improvements]
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | status_redo
Files: files | file ages | folders
SHA1:a5e9410f47546a641c52dc8f4848d46a769cfdcc
User & Date: bch 2012-01-06 05:20:53
Context
2012-01-06
05:28
corrections for erroneous merge of [4b432961ac|retro-sbsdiff] (see ticket [5a855f1bc6]) check-in: d7ff8932 user: bch tags: status_redo
05:20
undo [b9227b85cb|status improvements] check-in: a5e9410f user: bch tags: status_redo
2012-01-05
13:09
Merge the trunk changes into the retro-sbsdiff branch. check-in: 4b432961 user: drh tags: retro-sbsdiff
13:08
Update the built-in SQLite to the latest 3.7.10 beta. check-in: 8a8685d1 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/diff.c.

803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
    ** array of COPY/DELETE/INSERT triples.
    */
    free(c.aFrom);
    free(c.aTo);
    return c.aEdit;
  }
}

/*
** Copy a line with a limit. Used for side-by-side diffs to enforce a maximum
** line length limit.
*/
static char *copylimline(char *out, DLine *dl, int lim){
  int len;
  len = dl->h & LENGTH_MASK;
  if( lim && len > lim ){
    memcpy(out, dl->z, lim-3);
    memcpy(&out[lim-3], "...", 4);
  }else{
    memcpy(out, dl->z, len);
    out[len] = '\0';
  }
  return out;
}

/*
** Output table body of a side-by-side diff. Prior to the call, the caller
** should have output:
**   <table class="sbsdiff">
**   <tr><th colspan="2" class="diffhdr">Old title</th><th/>
**   <th colspan="2" class="diffhdr">New title</th></tr>
**
** And after the call, it should output:
**   </table>
**
** Some good reference diffs in the fossil repository for testing:
** /vdiff?from=080d27a&to=4b0f813&detail=1
** /vdiff?from=636804745b&to=c1d78e0556&detail=1
** /vdiff?from=c0b6c28d29&to=25169506b7&detail=1
** /vdiff?from=e3d022dffa&to=48bcfbd47b&detail=1
*/
int html_sbsdiff(
  Blob *pA_Blob,   /* FROM file */
  Blob *pB_Blob,   /* TO file */
  int nContext,    /* Amount of context to unified diff */
  int ignoreEolWs  /* Ignore whitespace at the end of lines */
){
  DContext c;
  int i;
  int iFrom, iTo;
  char *linebuf;
  int collim=0; /* Currently not settable; allows a column limit for diffs */
  int allowExp=0; /* Currently not settable; (dis)allow expansion of rows */

  /* Prepare the input files */
  memset(&c, 0, sizeof(c));
  c.aFrom = break_into_lines(blob_str(pA_Blob), blob_size(pA_Blob),
                             &c.nFrom, ignoreEolWs);
  c.aTo = break_into_lines(blob_str(pB_Blob), blob_size(pB_Blob),
                           &c.nTo, ignoreEolWs);
  if( c.aFrom==0 || c.aTo==0 ){
    free(c.aFrom);
    free(c.aTo);
    /* Note: This would be generated within a table. */
    @ <p class="generalError" style="white-space: nowrap">cannot compute
    @ difference between binary files</p>
    return 0;
  }

  collim = collim < 4 ? 0 : collim;

  /* Compute the difference */
  diff_all(&c);

  linebuf = fossil_malloc(LENGTH_MASK+1);
  if( !linebuf ){
    free(c.aFrom);
    free(c.aTo);
    free(c.aEdit);
    return 0;
  }

  iFrom=iTo=0;
  i=0;
  while( i<c.nEdit ){
    int j;
    /* Copied lines */
    for( j=0; j<c.aEdit[i]; j++){
      /* Hide lines which are copied and are further away from block boundaries
      ** than nContext lines. For each block with hidden lines, show a row
      ** notifying the user about the hidden rows.
      */
      if( j<nContext || j>c.aEdit[i]-nContext-1 ){
        @ <tr>
      }else if( j==nContext && j<c.aEdit[i]-nContext-1 ){
        @ <tr>
        @ <td class="meta" colspan="5" style="white-space: nowrap;">
        @ %d(c.aEdit[i]-2*nContext) hidden lines</td>
        @ </tr>
        if( !allowExp )
           continue;
        @ <tr style="display:none;">
      }else{
        if( !allowExp )
           continue;
        @ <tr style="display:none;">
      }

      copylimline(linebuf, &c.aFrom[iFrom+j], collim);
      @ <td class="lineno">%d(iFrom+j+1)</td>
      @ <td class="srcline">%h(linebuf)</td>

      @ <td> </td>

      copylimline(linebuf, &c.aTo[iTo+j], collim);
      @ <td class="lineno">%d(iTo+j+1)</td>
      @ <td class="srcline">%h(linebuf)</td>

      @ </tr>
    }
    iFrom+=c.aEdit[i];
    iTo+=c.aEdit[i];

    if( c.aEdit[i+1]!=0 && c.aEdit[i+2]!=0 ){
      int lim;
      lim = c.aEdit[i+1] > c.aEdit[i+2] ? c.aEdit[i+1] : c.aEdit[i+2];

      /* Assume changed lines */
      for( j=0; j<lim; j++ ){
        @ <tr>

        if( j<c.aEdit[i+1] ){
          copylimline(linebuf, &c.aFrom[iFrom+j], collim);
          @ <td class="changed lineno">%d(iFrom+j+1)</td>
          @ <td class="changed srcline">%h(linebuf)</td>
        }else{
          @ <td colspan="2" class="changedvoid"/>
        }

        @ <td class="changed">|</td>

        if( j<c.aEdit[i+2] ){
          copylimline(linebuf, &c.aTo[iTo+j], collim);
          @ <td class="changed lineno">%d(iTo+j+1)</td>
          @ <td class="changed srcline">%h(linebuf)</td>
        }else{
          @ <td colspan="2" class="changedvoid"/>
        }

        @ </tr>
      }
      iFrom+=c.aEdit[i+1];
      iTo+=c.aEdit[i+2];
    }else{

      /* Process deleted lines */
      for( j=0; j<c.aEdit[i+1]; j++ ){
        @ <tr>

        copylimline(linebuf, &c.aFrom[iFrom+j], collim);
        @ <td class="removed lineno">%d(iFrom+j+1)</td>
        @ <td class="removed srcline">%h(linebuf)</td>
        @ <td>&lt;</td>
        @ <td colspan="2" class="removedvoid"/>
        @ </tr>
      }
      iFrom+=c.aEdit[i+1];

      /* Process inserted lines */
      for( j=0; j<c.aEdit[i+2]; j++ ){
        @ <tr>
        @ <td colspan="2" class="addedvoid"/>
        @ <td>&gt;</td>
        copylimline(linebuf, &c.aTo[iTo+j], collim);
        @ <td class="added lineno">%d(iTo+j+1)</td>
        @ <td class="added srcline">%h(linebuf)</td>
        @ </tr>
      }
      iTo+=c.aEdit[i+2];
    }

    i+=3;
  }

  free(linebuf);
  free(c.aFrom);
  free(c.aTo);
  free(c.aEdit);
  return 1;
}


/*
** COMMAND: test-rawdiff
*/
void test_rawdiff_cmd(void){
  Blob a, b;
  int r;







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







803
804
805
806
807
808
809
























































































































































































810
811
812
813
814
815
816
    ** array of COPY/DELETE/INSERT triples.
    */
    free(c.aFrom);
    free(c.aTo);
    return c.aEdit;
  }
}

























































































































































































/*
** COMMAND: test-rawdiff
*/
void test_rawdiff_cmd(void){
  Blob a, b;
  int r;

Changes to src/info.c.

249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
...
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
...
316
317
318
319
320
321
322




323
324
325
326
327
328
329
...
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
...
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
....
1067
1068
1069
1070
1071
1072
1073

1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086

1087
1088
1089




1090
1091

1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
....
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
  }
}


/*
** Append the difference between two RIDs to the output
*/
static void append_diff(const char *zFrom, const char *zTo){
  int fromid;
  int toid;
  Blob from, to, out;
  if( zFrom ){
    fromid = uuid_to_rid(zFrom, 0);
    content_get(fromid, &from);
  }else{
................................................................................
  if( zTo ){
    toid = uuid_to_rid(zTo, 0);
    content_get(toid, &to);
  }else{
    blob_zero(&to);
  }
  blob_zero(&out);
  text_diff(&from, &to, &out, DIFF_IGNORE_EOLWS | 5);
  @ %h(blob_str(&out))
  blob_reset(&from);
  blob_reset(&to);
  blob_reset(&out);  
}


/*
** Write the difference between two RIDs to the output
*/
static void generate_sbsdiff(const char *zFrom, const char *zTo){
  int fromid;
  int toid;
  Blob from, to;
  if( zFrom ){
    fromid = uuid_to_rid(zFrom, 0);
    content_get(fromid, &from);
  }else{
    blob_zero(&from);
  }
  if( zTo ){
    toid = uuid_to_rid(zTo, 0);
    content_get(toid, &to);
  }else{
    blob_zero(&to);
  }
  @ <table class="sbsdiff">
  @ <tr><th colspan="2" class="diffhdr">Old (%S(zFrom))</th><th/>
  @ <th colspan="2" class="diffhdr">New (%S(zTo))</th></tr>
  html_sbsdiff(&from, &to, 5, 1);
  @ </table>
  blob_reset(&from);
  blob_reset(&to);
}


/*
** Write a line of web-page output that shows changes that have occurred 
** to a file between two check-ins.
*/
static void append_file_change_line(
  const char *zName,    /* Name of the file that has changed */
................................................................................
  const char *zOld,     /* blob.uuid before change.  NULL for added files */
  const char *zNew,     /* blob.uuid after change.  NULL for deletes */
  const char *zOldName, /* Prior name.  NULL if no name change. */
  int showDiff,         /* Show edit diffs if true */
  int sideBySide,       /* Show diffs side-by-side */
  int mperm             /* executable or symlink permission for zNew */
){




  if( !g.perm.History ){
    if( zNew==0 ){
      @ <p>Deleted %h(zName)</p>
    }else if( zOld==0 ){
      @ <p>Added %h(zName)</p>
    }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){
      @ <p>Name change from %h(zOldName) to %h(zName)
................................................................................
    }else if( fossil_strcmp(zNew, zOld)==0 ){
      @ <p>Execute permission %s(( mperm==PERM_EXE )?"set":"cleared")
      @  for %h(zName)</p>
    }else{
      @ <p>Changes to %h(zName)</p>
    }
    if( showDiff ){
      if( sideBySide ){
        generate_sbsdiff(zOld, zNew);
      }else{
        @ <blockquote><pre>
        append_diff(zOld, zNew);
        @ </pre></blockquote>
      }
    }
  }else{
    if( zOld && zNew ){
      if( fossil_strcmp(zOld, zNew)!=0 ){
        @ <p>Modified <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
        @ from <a href="%s(g.zTop)/artifact/%s(zOld)">[%S(zOld)]</a>
        @ to <a href="%s(g.zTop)/artifact/%s(zNew)">[%S(zNew)].</a>
................................................................................
      @ <p>Deleted <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
      @ version <a href="%s(g.zTop)/artifact/%s(zOld)">[%S(zOld)]</a>
    }else{
      @ <p>Added <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
      @ version <a href="%s(g.zTop)/artifact/%s(zNew)">[%S(zNew)]</a>
    }
    if( showDiff ){
      if( sideBySide ){
        generate_sbsdiff(zOld, zNew);
      }else{
        @ <blockquote><pre>
        append_diff(zOld, zNew);
        @ </pre></blockquote>
      }
    }else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){
      @ &nbsp;&nbsp;
      @ <a href="%s(g.zTop)/fdiff?v1=%S(zOld)&amp;v2=%S(zNew)">[diff]</a>
    }
    @ </p>
  }
}
................................................................................
void diff_page(void){
  int v1, v2;
  int isPatch;
  int sideBySide;
  Blob c1, c2, diff, *pOut;
  char *zV1;
  char *zV2;


  login_check_credentials();
  if( !g.perm.Read ){ login_needed(); return; }
  v1 = name_to_rid_www("v1");
  v2 = name_to_rid_www("v2");
  if( v1==0 || v2==0 ) fossil_redirect_home();
  sideBySide = atoi(PD("sbs","1"));
  zV1 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v1);
  zV2 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v2);
  isPatch = P("patch")!=0;
  if( isPatch ){
    pOut = cgi_output_blob();
    cgi_set_content_type("text/plain");

  }else{
    blob_zero(&diff);
    pOut = &diff;




  }
  if( !sideBySide || isPatch ){

    content_get(v1, &c1);
    content_get(v2, &c2);
    text_diff(&c1, &c2, pOut, 4 | 0);
    blob_reset(&c1);
    blob_reset(&c2);
  }
  if( !isPatch ){
    style_header("Diff");
    style_submenu_element("Patch", "Patch", "%s/fdiff?v1=%T&v2=%T&patch",
                          g.zTop, P("v1"), P("v2"));
    if( !sideBySide ){
      style_submenu_element("Side-by-side Diff", "sbsdiff",
                            "%s/fdiff?v1=%T&v2=%T&sbs=1",
................................................................................

    @ <h2>Differences From
    @ Artifact <a href="%s(g.zTop)/artifact/%S(zV1)">[%S(zV1)]</a>:</h2>
    object_description(v1, 0, 0);
    @ <h2>To Artifact <a href="%s(g.zTop)/artifact/%S(zV2)">[%S(zV2)]</a>:</h2>
    object_description(v2, 0, 0);
    @ <hr />
    if( sideBySide ){
      generate_sbsdiff(zV1, zV2);
    }else{
      @ <blockquote><pre>
      @ %h(blob_str(&diff))
      @ </pre></blockquote>
    }
    blob_reset(&diff);
    style_footer();
  }
}

/*
** WEBPAGE: raw







|







 







|






<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







>
>
>
>







 







|
<
<
<
|
|
<







 







|
<
<
<
|
|
<







 







>













>



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







 







|
<
<
<
|
|
<







249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
...
266
267
268
269
270
271
272
273
274
275
276
277
278
279





























280
281
282
283
284
285
286
...
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
...
305
306
307
308
309
310
311
312



313
314

315
316
317
318
319
320
321
...
331
332
333
334
335
336
337
338



339
340

341
342
343
344
345
346
347
....
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063

1064
1065
1066
1067
1068
1069

1070
1071
1072
1073
1074
1075
1076
....
1083
1084
1085
1086
1087
1088
1089
1090



1091
1092

1093
1094
1095
1096
1097
1098
1099
  }
}


/*
** Append the difference between two RIDs to the output
*/
static void append_diff(const char *zFrom, const char *zTo, int diffFlags){
  int fromid;
  int toid;
  Blob from, to, out;
  if( zFrom ){
    fromid = uuid_to_rid(zFrom, 0);
    content_get(fromid, &from);
  }else{
................................................................................
  if( zTo ){
    toid = uuid_to_rid(zTo, 0);
    content_get(toid, &to);
  }else{
    blob_zero(&to);
  }
  blob_zero(&out);
  text_diff(&from, &to, &out, diffFlags);
  @ %h(blob_str(&out))
  blob_reset(&from);
  blob_reset(&to);
  blob_reset(&out);  
}































/*
** Write a line of web-page output that shows changes that have occurred 
** to a file between two check-ins.
*/
static void append_file_change_line(
  const char *zName,    /* Name of the file that has changed */
................................................................................
  const char *zOld,     /* blob.uuid before change.  NULL for added files */
  const char *zNew,     /* blob.uuid after change.  NULL for deletes */
  const char *zOldName, /* Prior name.  NULL if no name change. */
  int showDiff,         /* Show edit diffs if true */
  int sideBySide,       /* Show diffs side-by-side */
  int mperm             /* executable or symlink permission for zNew */
){
  int diffFlags = DIFF_IGNORE_EOLWS | 7;
  if( sideBySide ){
    diffFlags |= DIFF_SIDEBYSIDE;
  }
  if( !g.perm.History ){
    if( zNew==0 ){
      @ <p>Deleted %h(zName)</p>
    }else if( zOld==0 ){
      @ <p>Added %h(zName)</p>
    }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){
      @ <p>Name change from %h(zOldName) to %h(zName)
................................................................................
    }else if( fossil_strcmp(zNew, zOld)==0 ){
      @ <p>Execute permission %s(( mperm==PERM_EXE )?"set":"cleared")
      @  for %h(zName)</p>
    }else{
      @ <p>Changes to %h(zName)</p>
    }
    if( showDiff ){
      @ <pre style="white-space:pre;">



      append_diff(zOld, zNew, diffFlags);
      @ </pre>

    }
  }else{
    if( zOld && zNew ){
      if( fossil_strcmp(zOld, zNew)!=0 ){
        @ <p>Modified <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
        @ from <a href="%s(g.zTop)/artifact/%s(zOld)">[%S(zOld)]</a>
        @ to <a href="%s(g.zTop)/artifact/%s(zNew)">[%S(zNew)].</a>
................................................................................
      @ <p>Deleted <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
      @ version <a href="%s(g.zTop)/artifact/%s(zOld)">[%S(zOld)]</a>
    }else{
      @ <p>Added <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
      @ version <a href="%s(g.zTop)/artifact/%s(zNew)">[%S(zNew)]</a>
    }
    if( showDiff ){
      @ <pre style="white-space:pre;">



      append_diff(zOld, zNew, diffFlags);
      @ </pre>

    }else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){
      @ &nbsp;&nbsp;
      @ <a href="%s(g.zTop)/fdiff?v1=%S(zOld)&amp;v2=%S(zNew)">[diff]</a>
    }
    @ </p>
  }
}
................................................................................
void diff_page(void){
  int v1, v2;
  int isPatch;
  int sideBySide;
  Blob c1, c2, diff, *pOut;
  char *zV1;
  char *zV2;
  int diffFlags;

  login_check_credentials();
  if( !g.perm.Read ){ login_needed(); return; }
  v1 = name_to_rid_www("v1");
  v2 = name_to_rid_www("v2");
  if( v1==0 || v2==0 ) fossil_redirect_home();
  sideBySide = atoi(PD("sbs","1"));
  zV1 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v1);
  zV2 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v2);
  isPatch = P("patch")!=0;
  if( isPatch ){
    pOut = cgi_output_blob();
    cgi_set_content_type("text/plain");
    diffFlags = 4;
  }else{
    blob_zero(&diff);
    pOut = &diff;
    if( sideBySide ){
      diffFlags = DIFF_IGNORE_EOLWS | DIFF_SIDEBYSIDE | 7;
    }else{
      diffFlags = DIFF_IGNORE_EOLWS | 7;
    }

  }
  content_get(v1, &c1);
  content_get(v2, &c2);
  text_diff(&c1, &c2, pOut, diffFlags);
  blob_reset(&c1);
  blob_reset(&c2);

  if( !isPatch ){
    style_header("Diff");
    style_submenu_element("Patch", "Patch", "%s/fdiff?v1=%T&v2=%T&patch",
                          g.zTop, P("v1"), P("v2"));
    if( !sideBySide ){
      style_submenu_element("Side-by-side Diff", "sbsdiff",
                            "%s/fdiff?v1=%T&v2=%T&sbs=1",
................................................................................

    @ <h2>Differences From
    @ Artifact <a href="%s(g.zTop)/artifact/%S(zV1)">[%S(zV1)]</a>:</h2>
    object_description(v1, 0, 0);
    @ <h2>To Artifact <a href="%s(g.zTop)/artifact/%S(zV2)">[%S(zV2)]</a>:</h2>
    object_description(v2, 0, 0);
    @ <hr />
    @ <pre style="while-space:pre;">



    @ %h(blob_str(&diff))
    @ </pre>

    blob_reset(&diff);
    style_footer();
  }
}

/*
** WEBPAGE: raw

Changes to src/skins.c.

151
152
153
154
155
156
157
158
159
160
161
162
163
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
200
201
202
203
204
205
206
207
208
209
...
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
...
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
....
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
@ }
@ 
@ /* The label/value pairs on (for example) the vinfo page */
@ table.label-value th {
@   vertical-align: top;
@   text-align: right;
@   padding: 0.2ex 2ex;
@ }
@
@ /* Side-by-side diff */
@ table.sbsdiff {
@   background-color: white;
@   font-family: fixed, Dejavu Sans Mono, Monaco, Lucida Console, monospace;
@   font-size: 8pt;
@   border-collapse:collapse;
@   white-space: pre;
@   width: 98%;
@   border: 1px #000 dashed;
@ }
@
@ table.sbsdiff th.diffhdr {
@   border-bottom: dotted;
@   border-width: 1px;
@ }
@
@ table.sbsdiff tr td {
@   white-space: pre;
@   padding-left: 3px;
@   padding-right: 3px;
@   margin: 0px;
@ }
@
@ table.sbsdiff tr td.lineno {
@   text-align: right;
@ }
@
@ table.sbsdiff tr td.meta {
@   color: white;
@   background-color: rgb(20, 20, 20);
@   text-align: center;
@ }
@
@ table.sbsdiff tr td.added {
@   background-color: rgb(230, 230, 230);
@ }
@
@ table.sbsdiff tr td.removed {
@   background-color: rgb(200, 200, 200);
@ }
@
@ table.sbsdiff tr td.changed {
@   background-color: rgb(220, 220, 220);
@ }');
@ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
@ <head>
@ <title>$<project_name>: $<title></title>
@ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
@       href="$home/timeline.rss">
@ <link rel="stylesheet" href="$home/style.css?blackwhite" type="text/css"
................................................................................
@ }
@ 
@ /* The label/value pairs on (for example) the ci page */
@ table.label-value th {
@   vertical-align: top;
@   text-align: right;
@   padding: 0.2ex 2ex;
@ }
@
@ /* Side-by-side diff */
@ table.sbsdiff {
@   background-color: #ffffc5;
@   font-family: fixed, Dejavu Sans Mono, Monaco, Lucida Console, monospace;
@   font-size: 8pt;
@   border-collapse:collapse;
@   white-space: pre;
@   width: 98%;
@   border: 1px #000 dashed;
@ }
@
@ table.sbsdiff th.diffhdr {
@   border-bottom: dotted;
@   border-width: 1px;
@ }
@
@ table.sbsdiff tr td {
@   white-space: pre;
@   padding-left: 3px;
@   padding-right: 3px;
@   margin: 0px;
@ }
@
@ table.sbsdiff tr td.lineno {
@   text-align: right;
@ }
@
@ table.sbsdiff tr td.meta {
@   background-color: #a09048;
@   text-align: center;
@ }
@
@ table.sbsdiff tr td.added {
@   background-color: rgb(210, 210, 100);
@ }
@
@ table.sbsdiff tr td.removed {
@   background-color: rgb(190, 200, 110);
@ }
@
@ table.sbsdiff tr td.changed {
@   background-color: rgb(200, 210, 120);
@ }');
@ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
@ <head>
@ <title>$<project_name>: $<title></title>
@ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
@       href="$home/timeline.rss">
@ <link rel="stylesheet" href="$home/style.css?tan" type="text/css"
................................................................................
@ }
@ 
@ /* The label/value pairs on (for example) the ci page */
@ table.label-value th {
@   vertical-align: top;
@   text-align: right;
@   padding: 0.2ex 2ex;
@ }
@
@ /* Side-by-side diff */
@ table.sbsdiff {
@   background-color: white;
@   font-family: fixed, Dejavu Sans Mono, Monaco, Lucida Console, monospace;
@   font-size: 6pt;
@   border-collapse:collapse;
@   white-space: pre;
@   width: 98%;
@   border: 1px #000 dashed;
@ }
@
@ table.sbsdiff th.diffhdr {
@   border-bottom: dotted;
@   border-width: 1px;
@ }
@
@ table.sbsdiff tr td {
@   white-space: pre;
@   padding-left: 3px;
@   padding-right: 3px;
@   margin: 0px;
@ }
@
@ table.sbsdiff tr td.lineno {
@   text-align: right;
@ }
@
@ table.sbsdiff tr td.meta {
@   color: white;
@   background-color: black;
@   text-align: center;
@ }
@
@ table.sbsdiff tr td.added {
@   background-color: white;
@ }
@
@ table.sbsdiff tr td.removed {
@   background-color: white;
@   text-decoration: line-through;
@ }
@
@ table.sbsdiff tr td.changed {
@   background-color: white;
@ }');
@ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
@ <head>
@ <title>$<project_name>: $<title></title>
@ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
@       href="$home/timeline.rss">
@ <link rel="stylesheet" href="$home/style.css?black2" type="text/css"
................................................................................
@ 
@ table.report tr td {
@   padding: 3px 5px;
@ }
@ 
@ textarea {
@   font-size: 1em;
@ }
@
@ /* Side-by-side diff */
@ table.sbsdiff {
@   background-color: white;
@   font-family: Dejavu Sans Mono, Monaco, Lucida Console, monospace;
@   font-size: 6pt;
@   border-collapse:collapse;
@   width: 98%;
@   border: 1px #000 dashed;
@   margin-left: auto;
@   margin-right: auto;
@ }
@
@ table.sbsdiff th.diffhdr {
@   border-bottom: dotted;
@   border-width: 1px;
@ }
@
@ table.sbsdiff tr td {
@   padding-left: 3px;
@   padding-right: 3px;
@   margin: 0px;
@   vertical-align: top;
@   white-space: pre-wrap;
@ }
@
@ table.sbsdiff tr td.lineno {
@   text-align: right;
@   /* border-bottom: 1px solid rgb(220, 220, 220); */
@ }
@
@ table.sbsdiff tr td.srcline {
@   /* max-width: 400px; */
@   /* Note: May partially hide long lines without whitespaces */
@   /* overflow: hidden; */
@   /* border-bottom: 1px solid rgb(220, 220, 220); */
@ }
@
@ table.sbsdiff tr td.meta {
@   background-color: rgb(170, 160, 255);
@   padding-top: 0.25em;
@   padding-bottom: 0.25em;
@   text-align: center;
@   -moz-border-radius: 5px;
@   -moz-border-radius: 5px;
@   -webkit-border-radius: 5px;
@   -webkit-border-radius: 5px;
@   -border-radius: 5px;
@   -border-radius: 5px;
@   border-radius: 5px;
@   border-radius: 5px;
@ }
@
@ table.sbsdiff tr td.added {
@   background-color: rgb(180, 250, 180);
@   /* border-bottom: 1px solid rgb(160, 230, 160); */
@ }
@
@ table.sbsdiff tr td.removed {
@   background-color: rgb(250, 130, 130);
@   /* border-bottom: 1px solid rgb(230, 110, 110); */
@ }
@
@ table.sbsdiff tr td.changed {
@   background-color: rgb(210, 210, 200);
@   /* border-bottom: 1px solid rgb(190, 190, 180); */
@ }');
@ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
@ <head>
@ <title>$<project_name>: $<title></title>
@ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
@       href="$home/timeline.rss">
@ <link rel="stylesheet" href="$home/style.css?black2" type="text/css"







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







151
152
153
154
155
156
157













































158
159
160
161
162
163
164
...
353
354
355
356
357
358
359












































360
361
362
363
364
365
366
...
589
590
591
592
593
594
595














































596
597
598
599
600
601
602
...
887
888
889
890
891
892
893



































































894
895
896
897
898
899
900
@ }
@ 
@ /* The label/value pairs on (for example) the vinfo page */
@ table.label-value th {
@   vertical-align: top;
@   text-align: right;
@   padding: 0.2ex 2ex;













































@ }');
@ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
@ <head>
@ <title>$<project_name>: $<title></title>
@ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
@       href="$home/timeline.rss">
@ <link rel="stylesheet" href="$home/style.css?blackwhite" type="text/css"
................................................................................
@ }
@ 
@ /* The label/value pairs on (for example) the ci page */
@ table.label-value th {
@   vertical-align: top;
@   text-align: right;
@   padding: 0.2ex 2ex;












































@ }');
@ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
@ <head>
@ <title>$<project_name>: $<title></title>
@ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
@       href="$home/timeline.rss">
@ <link rel="stylesheet" href="$home/style.css?tan" type="text/css"
................................................................................
@ }
@ 
@ /* The label/value pairs on (for example) the ci page */
@ table.label-value th {
@   vertical-align: top;
@   text-align: right;
@   padding: 0.2ex 2ex;














































@ }');
@ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
@ <head>
@ <title>$<project_name>: $<title></title>
@ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
@       href="$home/timeline.rss">
@ <link rel="stylesheet" href="$home/style.css?black2" type="text/css"
................................................................................
@ 
@ table.report tr td {
@   padding: 3px 5px;
@ }
@ 
@ textarea {
@   font-size: 1em;



































































@ }');
@ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
@ <head>
@ <title>$<project_name>: $<title></title>
@ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
@       href="$home/timeline.rss">
@ <link rel="stylesheet" href="$home/style.css?black2" type="text/css"

Changes to src/style.c.

396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
@
@ /* The label/value pairs on (for example) the ci page */
@ table.label-value th {
@   vertical-align: top;
@   text-align: right;
@   padding: 0.2ex 2ex;
@ }
@
@ /* Side-by-side diff */
@ table.sbsdiff {
@   background-color: white;
@   font-family: fixed, Dejavu Sans Mono, Monaco, Lucida Console, monospace;
@   font-size: 8pt;
@   border-collapse:collapse;
@   white-space: pre;
@   width: 98%;
@   border: 1px #000 dashed;
@   margin-left: auto;
@   margin-right: auto;
@ }
@
@ table.sbsdiff th.diffhdr {
@   border-bottom: dotted;
@   border-width: 1px;
@ }
@
@ table.sbsdiff tr td {
@   white-space: pre;
@   padding-left: 3px;
@   padding-right: 3px;
@   margin: 0px;
@   vertical-align: top;
@ }
@
@ table.sbsdiff tr td.lineno {
@   text-align: right;
@ }
@
@ table.sbsdiff tr td.srcline {
@ }
@
@ table.sbsdiff tr td.meta {
@   background-color: rgb(170, 160, 255);
@   text-align: center;
@ }
@
@ table.sbsdiff tr td.added {
@   background-color: rgb(180, 250, 180);
@ }
@ table.sbsdiff tr td.addedvoid {
@   background-color: rgb(190, 190, 180);
@ }
@
@ table.sbsdiff tr td.removed {
@   background-color: rgb(250, 130, 130);
@ }
@ table.sbsdiff tr td.removedvoid {
@   background-color: rgb(190, 190, 180);
@ }
@
@ table.sbsdiff tr td.changed {
@   background-color: rgb(210, 210, 200);
@ }
@ table.sbsdiff tr td.changedvoid {
@   background-color: rgb(190, 190, 180);
@ }
@
;


/* The following table contains bits of default CSS that must
** be included if they are not found in the application-defined
** CSS.
*/







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







396
397
398
399
400
401
402




























































403
404
405
406
407
408
409
@
@ /* The label/value pairs on (for example) the ci page */
@ table.label-value th {
@   vertical-align: top;
@   text-align: right;
@   padding: 0.2ex 2ex;
@ }




























































;


/* The following table contains bits of default CSS that must
** be included if they are not found in the application-defined
** CSS.
*/

Changes to src/vfile.c.

122
123
124
125
126
127
128
129

130
131
132
133
134
135
136
137
138
139
140
141



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
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
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221



222
223
224
225
226
227
228
229
230
231
232
233
234
235
  db_finalize(&ridq);
  db_finalize(&ins);
  manifest_destroy(p);
  db_end_transaction(0);
}

/*
** Look at every VFILE entry with the given vid and  set update

** VFILE.CHNGED field on every file according to whether or not
** the file has changes.  0 means no change.  1 means edited.  2 means
** the file has changed due to a merge.  3 means the file was added
** by a merge.
**
** If VFILE.DELETED is true or if VFILE.RID is zero, then the file was
** either removed from managemented via "fossil rm" or added via
** "fossil add", respectively, and in both cases we always know that 
** the file has changed without having the check the size, mtime,
** or on-disk content.
**
** If the size of the file has changed, then we always know that the file



** changed without having to look at the mtime or on-disk content.
**
** The mtime of the file is only a factor if the mtime-changes setting
** is false and the useSha1sum flag is false.  If the mtime-changes
** setting is true (or undefined - it defaults to true) or if useSha1sum
** is true, then we do not trust the mtime and will examine the on-disk
** content to determine if a file really is the same.
**
** If the mtime is used, it is used only to determine if files are the same.
** If the mtime of a file has changed, we still examine the on-disk content
** to see whether or not the edit was a null-edit.
*/
void vfile_check_signature(int vid, int notFileIsFatal, int useSha1sum){
  int nErr = 0;
  Stmt q;
  Blob fileCksum, origCksum;
  int useMtime = useSha1sum==0 && db_get_boolean("mtime-changes", 1);

  db_begin_transaction();
  db_prepare(&q, "SELECT id, %Q || pathname,"
                 "       vfile.mrid, deleted, chnged, uuid, size, mtime"
                 "  FROM vfile LEFT JOIN blob ON vfile.mrid=blob.rid"
                 " WHERE vid=%d ", g.zLocalRoot, vid);
  while( db_step(&q)==SQLITE_ROW ){
    int id, rid, isDeleted;
    const char *zName;
    int chnged = 0;
    int oldChnged;
    i64 oldMtime;
    i64 currentMtime;
    i64 origSize;
    i64 currentSize;

    id = db_column_int(&q, 0);
    zName = db_column_text(&q, 1);
    rid = db_column_int(&q, 2);
    isDeleted = db_column_int(&q, 3);
    oldChnged = chnged = db_column_int(&q, 4);
    oldMtime = db_column_int64(&q, 7);
    currentSize = file_wd_size(zName);
    origSize = db_column_int64(&q, 6);
    currentMtime = file_wd_mtime(0);
    if( chnged==0 && (isDeleted || rid==0) ){
      /* "fossil rm" or "fossil add" always change the file */
      chnged = 1;
    }else if( !file_wd_isfile_or_link(0) && currentSize>=0 ){
      if( notFileIsFatal ){
        fossil_warning("not an ordinary file: %s", zName);
        nErr++;
      }
      chnged = 1;




    }
    if( origSize!=currentSize ){
      if( chnged==0 ){



        /* A file size change is definitive - the file has changed.  No
        ** need to check the mtime or sha1sum */
        chnged = 1;
      }
    }else if( (chnged==1 || chnged==2) && rid!=0 && !isDeleted ){
      /* File is believed to have changed but it is the same size.
      ** Double check that it really has changed by looking at content. */
      assert( origSize==currentSize );
      db_ephemeral_blob(&q, 5, &origCksum);
      if( sha1sum_file(zName, &fileCksum) ){
        blob_zero(&fileCksum);
      }
      if( blob_compare(&fileCksum, &origCksum)==0 ) chnged = 0;
      blob_reset(&origCksum);
      blob_reset(&fileCksum);
    }else if( chnged==0 && (useMtime==0 || currentMtime!=oldMtime) ){
      /* For files that were formerly believed to be unchanged, if their
      ** mtime changes, or unconditionally if --sha1sum is used, check
      ** to see if they have been edited by looking at their SHA1 sum */
      assert( origSize==currentSize );
      db_ephemeral_blob(&q, 5, &origCksum);
      if( sha1sum_file(zName, &fileCksum) ){
        blob_zero(&fileCksum);
      }
      if( blob_compare(&fileCksum, &origCksum) ){
        chnged = 1;



      }
      blob_reset(&origCksum);
      blob_reset(&fileCksum);
    }
    if( currentMtime!=oldMtime || chnged!=oldChnged ){
      db_multi_exec("UPDATE vfile SET mtime=%lld, chnged=%d WHERE id=%d",
                    currentMtime, chnged, id);
    }
  }
  db_finalize(&q);
  if( nErr ) fossil_fatal("abort due to prior errors");
  db_end_transaction(0);
}








|
>
|
<
|
|

|
<
<
|
<

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





|













<
<





|

|
<
<
<
<

|





>
>
>
>

<
|
>
>
>

|


<
<
<
<
<
<
<
|
<
<
<
|
<
<
<
<






>
>
>




|
|
<







122
123
124
125
126
127
128
129
130
131

132
133
134
135


136

137
138
139
140
141
142










143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161


162
163
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
200
201
202
203
204
205
206

207
208
209
210
211
212
213
  db_finalize(&ridq);
  db_finalize(&ins);
  manifest_destroy(p);
  db_end_transaction(0);
}

/*
** Check the file signature of the disk image for every VFILE of vid.
**
** Set the VFILE.CHNGED field on every file that has changed.  Also 

** set VFILE.CHNGED on every folder that contains a file or folder 
** that has changed.
**
** If VFILE.DELETED is null or if VFILE.RID is zero, then we can assume


** the file has changed without having the check the on-disk image.

**
** If the size of the file has changed, then we assume that it has
** changed.  If the mtime of the file has not changed and useSha1sum is false
** and the mtime-changes setting is true (the default) then we assume that
** the file has not changed.  If the mtime has changed, we go ahead and
** double-check that the file has changed by looking at its SHA1 sum.










*/
void vfile_check_signature(int vid, int notFileIsFatal, int useSha1sum){
  int nErr = 0;
  Stmt q;
  Blob fileCksum, origCksum;
  int checkMtime = useSha1sum==0 && db_get_boolean("mtime-changes", 1);

  db_begin_transaction();
  db_prepare(&q, "SELECT id, %Q || pathname,"
                 "       vfile.mrid, deleted, chnged, uuid, size, mtime"
                 "  FROM vfile LEFT JOIN blob ON vfile.mrid=blob.rid"
                 " WHERE vid=%d ", g.zLocalRoot, vid);
  while( db_step(&q)==SQLITE_ROW ){
    int id, rid, isDeleted;
    const char *zName;
    int chnged = 0;
    int oldChnged;
    i64 oldMtime;
    i64 currentMtime;



    id = db_column_int(&q, 0);
    zName = db_column_text(&q, 1);
    rid = db_column_int(&q, 2);
    isDeleted = db_column_int(&q, 3);
    oldChnged = db_column_int(&q, 4);
    oldMtime = db_column_int64(&q, 7);
    if( isDeleted ){




      chnged = 1;
    }else if( !file_wd_isfile_or_link(zName) && file_wd_size(0)>=0 ){
      if( notFileIsFatal ){
        fossil_warning("not an ordinary file: %s", zName);
        nErr++;
      }
      chnged = 1;
    }else if( oldChnged>=2 ){
      chnged = oldChnged;
    }else if( rid==0 ){
      chnged = 1;
    }

    if( chnged!=1 ){
      i64 origSize = db_column_int64(&q, 6);
      currentMtime = file_wd_mtime(0);
      if( origSize!=file_wd_size(0) ){
        /* A file size change is definitive - the file has changed.  No
        ** need to check the sha1sum */
        chnged = 1;
      }







    }



    if( chnged!=1 && (checkMtime==0 || currentMtime!=oldMtime) ){




      db_ephemeral_blob(&q, 5, &origCksum);
      if( sha1sum_file(zName, &fileCksum) ){
        blob_zero(&fileCksum);
      }
      if( blob_compare(&fileCksum, &origCksum) ){
        chnged = 1;
      }else if( currentMtime!=oldMtime ){
        db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d",
                      currentMtime, id);
      }
      blob_reset(&origCksum);
      blob_reset(&fileCksum);
    }
    if( chnged!=oldChnged && (chnged || !checkMtime) ){
      db_multi_exec("UPDATE vfile SET chnged=%d WHERE id=%d", chnged, id);

    }
  }
  db_finalize(&q);
  if( nErr ) fossil_fatal("abort due to prior errors");
  db_end_transaction(0);
}