Changes On Branch use-blob_strip_bom
Not logged in

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

Changes In Branch use-blob_strip_bom Excluding Merge-Ins

This is equivalent to a diff from db0c512767 to b0e05a90b6

2012-11-05
21:10
Do not run the graphical merging tool nor leave merge-droppings after a dry-run merge. Also improve the merge summary message at the end of a merge. check-in: cd2c0e4cb5 user: drh tags: trunk
13:56
merge trunk Leaf check-in: b0e05a90b6 user: jan.nijtmans tags: use-blob_strip_bom
13:10
If the committed file has CR/NL or UTF-16 (or both), give the user the possibility to convert it to resp NL or UTF-8 (or both) without committing check-in: c6223a8e2a user: jan.nijtmans tags: convert_before_commit
2012-11-04
18:03
merge trunk check-in: e86aa2a1e8 user: jan.nijtmans tags: improve_commit_warning
17:41
Merge the "spelling" branch into trunk, fixing a huge number of typos, mostly in comments, but occasionally in error messages or help screens. check-in: db0c512767 user: drh tags: trunk
12:59
Fix typos. Closed-Leaf check-in: 45065c5c28 user: dmitry tags: spelling
11:58
Improvements to the fix for [0ff64b0a5fc88e7e]: (1) Better error message and (2) allow the partial commit of the renamed file as long as its destination files is also part of the partial commit. check-in: c0fe455c78 user: drh tags: trunk
2012-11-01
14:02
bug-fix: Before preparing a diff, BOM's should not be removed. It might result in a BOM in the middle of UTF-8, which is invalid, but that's how diff works. check-in: cd06b7d8af user: jan.nijtmans tags: use-blob_strip_bom

Changes to src/blob.c.

  1089   1089     *pRight = swap;
  1090   1090   }
  1091   1091   
  1092   1092   /*
  1093   1093   ** Strip a possible BOM from the blob. On Windows, if there
  1094   1094   ** is either no BOM at all or an (le/be) UTF-16 BOM, a conversion
  1095   1095   ** to UTF-8 is done.
  1096         -** If useMbcs is false and there is no BOM, the input string
         1096  +** If useMbcs is 0 and there is no BOM, the input string
  1097   1097   ** is assumed to be UTF-8 already, so no conversion is done.
         1098  +** If useMbcs is 2, any BOM is replaced by the UTF-8 BOM
  1098   1099   */
  1099   1100   void blob_strip_bom(Blob *pBlob, int useMbcs){
  1100   1101     static const unsigned char bom[] = { 0xEF, 0xBB, 0xBF };
  1101   1102   #ifdef _WIN32
  1102   1103     static const unsigned short ubom = 0xfeff;
  1103   1104     static const unsigned short urbom = 0xfffe;
  1104   1105   #endif /* _WIN32 */
  1105   1106     char *zUtf8;
  1106   1107     if( blob_size(pBlob)>2 && memcmp(blob_buffer(pBlob), bom, 3)==0 ) {
  1107         -	struct Blob temp;
  1108         -    zUtf8 = blob_str(pBlob) + 3;
  1109         -    blob_zero(&temp);
  1110         -    blob_append(&temp, zUtf8, -1);
  1111         -    fossil_mbcs_free(zUtf8);
  1112         -    blob_swap(pBlob, &temp);
  1113         -    blob_reset(&temp);
         1108  +    if( useMbcs<2 ){
         1109  +      struct Blob temp;
         1110  +      zUtf8 = blob_str(pBlob) + 3;
         1111  +      blob_zero(&temp);
         1112  +      blob_append(&temp, zUtf8, -1);
         1113  +      fossil_mbcs_free(zUtf8);
         1114  +      blob_swap(pBlob, &temp);
         1115  +      blob_reset(&temp);
         1116  +    }
  1114   1117   #ifdef _WIN32
  1115   1118     }else if( blob_size(pBlob)>1 && (blob_size(pBlob)&1)==0
  1116   1119         && memcmp(blob_buffer(pBlob), &ubom, 2)==0 ) {
  1117   1120       /* Make sure the blob contains two terminating 0-bytes */
  1118   1121       blob_append(pBlob, "", 1);
  1119   1122       zUtf8 = blob_str(pBlob) + 2;
  1120   1123       zUtf8 = fossil_unicode_to_utf8(zUtf8);
  1121   1124       blob_zero(pBlob);
         1125  +    if( useMbcs>1 ){
         1126  +      blob_append(pBlob, (char*)bom, 3);
         1127  +    }
  1122   1128       blob_append(pBlob, zUtf8, -1);
  1123   1129       fossil_mbcs_free(zUtf8);
  1124   1130     }else if( blob_size(pBlob)>1 && (blob_size(pBlob)&1)==0
  1125   1131         && memcmp(blob_buffer(pBlob), &urbom, 2)==0 ) {
  1126   1132       unsigned int i = blob_size(pBlob);
  1127   1133       zUtf8 = blob_buffer(pBlob);
  1128   1134       while( i > 0 ){
................................................................................
  1132   1138           zUtf8[--i] = temp;
  1133   1139       }
  1134   1140       /* Make sure the blob contains two terminating 0-bytes */
  1135   1141       blob_append(pBlob, "", 1);
  1136   1142       zUtf8 = blob_str(pBlob) + 2;
  1137   1143       zUtf8 = fossil_unicode_to_utf8(zUtf8);
  1138   1144       blob_zero(pBlob);
         1145  +    if( useMbcs>1 ){
         1146  +      blob_append(pBlob, (char*)bom, 3);
         1147  +    }
  1139   1148       blob_append(pBlob, zUtf8, -1);
  1140   1149       fossil_mbcs_free(zUtf8);
  1141         -  }else if (useMbcs) {
         1150  +  }else if (useMbcs==1) {
  1142   1151       zUtf8 = fossil_mbcs_to_utf8(blob_str(pBlob));
  1143   1152       blob_zero(pBlob);
  1144   1153       blob_append(pBlob, zUtf8, -1);
  1145   1154       fossil_mbcs_free(zUtf8);
  1146   1155   #endif /* _WIN32 */
  1147   1156     }
  1148   1157   }

Changes to src/diff.c.

    43     43   /*
    44     44   ** These error messages are shared in multiple locations.  They are defined
    45     45   ** here for consistency.
    46     46   */
    47     47   #define DIFF_CANNOT_COMPUTE_BINARY \
    48     48       "cannot compute difference between binary files\n"
    49     49   
           50  +#define DIFF_CANNOT_COMPUTE_ENCODING \
           51  +    "cannot compute difference between files with different encodings\n"
           52  +
    50     53   #define DIFF_CANNOT_COMPUTE_SYMLINK \
    51     54       "cannot compute difference between symlink and regular file\n"
    52     55   
    53         -#define looks_like_binary(blob) (looks_like_utf8((blob)) == 0)
           56  +#define looks_like_text(blob) (looks_like_utf8(blob)&3)
    54     57   #endif /* INTERFACE */
    55     58   
    56     59   /*
    57     60   ** Maximum length of a line in a text file, in bytes.  (8192)
    58     61   */
    59     62   #define LENGTH_MASK_SZ  13
    60     63   #define LENGTH_MASK     ((1<<LENGTH_MASK_SZ)-1)
................................................................................
   181    184   **         not be UTF-8.
   182    185   **
   183    186   **  (0) -- The content appears to be binary because it contains embedded
   184    187   **         NUL characters or an extremely long line.  Since this function
   185    188   **         does not understand UTF-16, it may falsely consider UTF-16 text
   186    189   **         to be binary.
   187    190   **
   188         -** (-1) -- The content appears to consist entirely of text, with lines
          191  +** (-1,-2) UTF-16 (le/be)
          192  +**
          193  +** (-3) -- The content appears to consist entirely of text, with lines
   189    194   **         delimited by carriage-return, line-feed pairs; however, the
   190    195   **         encoding may not be UTF-8.
   191    196   **
   192    197   ************************************ WARNING **********************************
   193    198   **
   194    199   ** This function does not validate that the blob content is properly formed
   195    200   ** UTF-8.  It assumes that all code points are the same size.  It does not
................................................................................
   209    214   
   210    215     /* Check individual lines.
   211    216     */
   212    217     if( n==0 ) return result;  /* Empty file -> text */
   213    218     c = *z;
   214    219     if( c==0 ) return 0;  /* Zero byte in a file -> binary */
   215    220     j = (c!='\n');
          221  +  if ( (n&1)==0 ){ /* UTF-16 must have an even blob length */
          222  +    if ( (c==0xff) && (z[1]==0xfe) ){ /* UTF-16 LE BOM */
          223  +      result = -1;
          224  +      while( (n-=2)>0 ){
          225  +        c = *(z+=2); ++j;
          226  +        if( z[1]==0 ){ /* High-byte must be 0 for further checks */
          227  +          if( c==0 ) return 0;  /* Zero char in a file -> binary */
          228  +          if( c=='\n' ){
          229  +            if( j>LENGTH_MASK ){
          230  +              return 0;  /* Very long line -> binary */
          231  +            }
          232  +            j = 0;
          233  +          }
          234  +        }
          235  +        if( j>LENGTH_MASK ){
          236  +          return 0;  /* Very long line -> binary */
          237  +        }
          238  +      }
          239  +      return result;
          240  +    } else if ( (c==0xfe) && (z[1]==0xff) ){ /* UTF-16 BE BOM */
          241  +      result = -2;
          242  +      ++z;
          243  +      while( (n-=2)>0 ){
          244  +        c = *(z+=2); ++j;
          245  +        if ( z[-1]==0 ){ /* High-byte must be 0 for further checks */
          246  +          if( c==0 ) return 0;  /* Zero char in a file -> binary */
          247  +          if( c=='\n' ){
          248  +            if( j>LENGTH_MASK ){
          249  +              return 0;  /* Very long line -> binary */
          250  +            }
          251  +            j = 0;
          252  +          }
          253  +        }
          254  +        if( j>LENGTH_MASK ){
          255  +          return 0;  /* Very long line -> binary */
          256  +        }
          257  +      }
          258  +      return result;
          259  +    }
          260  +  }
   216    261     while( --n>0 ){
   217    262       c = *++z; ++j;
   218    263       if( c==0 ) return 0;  /* Zero byte in a file -> binary */
   219    264       if( c=='\n' ){
   220    265         int c2 = z[-1];
   221    266         if( c2=='\r' ){
   222    267           result = -1;  /* Contains CR/NL, continue */
................................................................................
   241    286   #    define WCHAR_T wchar_t
   242    287   #  else
   243    288   #    define WCHAR_T unsigned short
   244    289   #  endif
   245    290   #endif
   246    291   
   247    292   /*
   248         -** Maximum length of a line in a text file, in UTF-16 characters.  (4096)
   249         -** The number of bytes represented by this value cannot exceed LENGTH_MASK
   250         -** bytes, because that is the line buffer size used by the diff engine.
          293  +** Maximum length of a line in a text file, in UTF-16 characters.  (2731)
          294  +** The number of characters represented by this value cannot exceed
          295  +** LENGTH_UTF16_LENGTH_MASK characters, because when converting UTF-16
          296  +** to UTF-8 it could overflow the line buffer used by the diff engine.
   251    297   */
   252         -#define UTF16_LENGTH_MASK_SZ  (LENGTH_MASK_SZ-(sizeof(WCHAR_T)-sizeof(char)))
   253         -#define UTF16_LENGTH_MASK     ((1<<UTF16_LENGTH_MASK_SZ)-1)
          298  +#define UTF16_LENGTH_MASK     (LENGTH_MASK/3)
   254    299   
   255    300   /*
   256    301   ** The carriage-return / line-feed characters in the UTF-16be and UTF-16le
   257    302   ** encodings.
   258    303   */
   259    304   #define UTF16BE_CR  ((WCHAR_T)'\r')
   260    305   #define UTF16BE_LF  ((WCHAR_T)'\n')

Changes to src/diffcmd.c.

    74     74   **
    75     75   ** When using an external diff program, zBinGlob contains the GLOB patterns
    76     76   ** for file names to treat as binary.  If fIncludeBinary is zero, these files
    77     77   ** will be skipped in addition to files that may contain binary content.
    78     78   */
    79     79   void diff_file(
    80     80     Blob *pFile1,             /* In memory content to compare from */
    81         -  int isBin1,               /* Does the 'from' content appear to be binary */
           81  +  int eType1,               /* Does the 'from' content appear to be text */
    82     82     const char *zFile2,       /* On disk content to compare to */
    83     83     const char *zName,        /* Display name of the file */
    84     84     const char *zDiffCmd,     /* Command for comparison */
    85     85     const char *zBinGlob,     /* Treat file names matching this as binary */
    86     86     int fIncludeBinary,       /* Include binary files for external diff */
    87     87     u64 diffFlags             /* Flags to control the diff */
    88     88   ){
    89     89     if( zDiffCmd==0 ){
    90     90       Blob out;                 /* Diff output text */
    91     91       Blob file2;               /* Content of zFile2 */
    92     92       const char *zName2;       /* Name of zFile2 for display */
           93  +    int eType2 = 0;
    93     94   
    94     95       /* Read content of zFile2 into memory */
    95     96       blob_zero(&file2);
    96     97       if( file_wd_size(zFile2)<0 ){
    97     98         zName2 = NULL_DEVICE;
    98     99       }else{
    99    100         if( file_wd_islink(zFile2) ){
   100    101           blob_read_link(&file2, zFile2);
   101    102         }else{
   102    103           blob_read_from_file(&file2, zFile2);
   103    104         }
   104    105         zName2 = zName;
   105    106       }
   106         -
          107  +    if( !fIncludeBinary ){
          108  +      eType2 = looks_like_text(&file2);
          109  +    }
   107    110       /* Compute and output the differences */
   108    111       if( diffFlags & DIFF_BRIEF ){
   109    112         if( blob_compare(pFile1, &file2) ){
   110    113           fossil_print("CHANGED  %s\n", zName);
   111    114         }
          115  +    }else if( eType1!=eType2 ){
          116  +      fossil_print(DIFF_CANNOT_COMPUTE_ENCODING);
   112    117       }else{
          118  +      blob_strip_bom(pFile1, 2);
          119  +      blob_strip_bom(&file2, 2);
   113    120         blob_zero(&out);
   114    121         text_diff(pFile1, &file2, &out, diffFlags);
   115    122         if( blob_size(&out) ){
   116    123           diff_print_filenames(zName, zName2, diffFlags);
   117    124           fossil_print("%s\n", blob_str(&out));
   118    125         }
   119    126         blob_reset(&out);
................................................................................
   124    131     }else{
   125    132       int cnt = 0;
   126    133       Blob nameFile1;    /* Name of temporary file to old pFile1 content */
   127    134       Blob cmd;          /* Text of command to run */
   128    135   
   129    136       if( !fIncludeBinary ){
   130    137         Blob file2;
   131         -      if( isBin1 ){
          138  +      int eType2;
          139  +      if( eType1!=1 ){
   132    140           fossil_print(DIFF_CANNOT_COMPUTE_BINARY);
   133    141           return;
   134    142         }
   135    143         if( zBinGlob ){
   136    144           Glob *pBinary = glob_create(zBinGlob);
   137    145           if( glob_match(pBinary, zName) ){
   138    146             fossil_print(DIFF_CANNOT_COMPUTE_BINARY);
................................................................................
   145    153         if( file_wd_size(zFile2)>=0 ){
   146    154           if( file_wd_islink(zFile2) ){
   147    155             blob_read_link(&file2, zFile2);
   148    156           }else{
   149    157             blob_read_from_file(&file2, zFile2);
   150    158           }
   151    159         }
   152         -      if( looks_like_binary(&file2) ){
          160  +      eType2 = looks_like_text(&file2);
          161  +      if( eType2!=1 ){
   153    162           fossil_print(DIFF_CANNOT_COMPUTE_BINARY);
   154    163           blob_reset(&file2);
   155    164           return;
   156    165         }
   157    166         blob_reset(&file2);
   158    167       }
   159    168   
................................................................................
   195    204   ** When using an external diff program, zBinGlob contains the GLOB patterns
   196    205   ** for file names to treat as binary.  If fIncludeBinary is zero, these files
   197    206   ** will be skipped in addition to files that may contain binary content.
   198    207   */
   199    208   void diff_file_mem(
   200    209     Blob *pFile1,             /* In memory content to compare from */
   201    210     Blob *pFile2,             /* In memory content to compare to */
   202         -  int isBin1,               /* Does the 'from' content appear to be binary */
   203         -  int isBin2,               /* Does the 'to' content appear to be binary */
          211  +  int eType,                /* Does the content appear to be text */
   204    212     const char *zName,        /* Display name of the file */
   205    213     const char *zDiffCmd,     /* Command for comparison */
   206    214     const char *zBinGlob,     /* Treat file names matching this as binary */
   207    215     int fIncludeBinary,       /* Include binary files for external diff */
   208    216     u64 diffFlags             /* Diff flags */
   209    217   ){
   210    218     if( diffFlags & DIFF_BRIEF ) return;
   211    219     if( zDiffCmd==0 ){
   212    220       Blob out;      /* Diff output text */
   213    221   
   214    222       blob_zero(&out);
          223  +    blob_strip_bom(pFile1, 2);
          224  +    blob_strip_bom(pFile2, 2);
   215    225       text_diff(pFile1, pFile2, &out, diffFlags);
   216    226       diff_print_filenames(zName, zName, diffFlags);
   217    227       fossil_print("%s\n", blob_str(&out));
   218    228   
   219    229       /* Release memory resources */
   220    230       blob_reset(&out);
   221    231     }else{
   222    232       Blob cmd;
   223    233       char zTemp1[300];
   224    234       char zTemp2[300];
   225    235   
   226    236       if( !fIncludeBinary ){
   227         -      if( isBin1 || isBin2 ){
          237  +      if( eType==0 ){
   228    238           fossil_print(DIFF_CANNOT_COMPUTE_BINARY);
   229    239           return;
   230    240         }
   231    241         if( zBinGlob ){
   232    242           Glob *pBinary = glob_create(zBinGlob);
   233    243           if( glob_match(pBinary, zName) ){
   234    244             fossil_print(DIFF_CANNOT_COMPUTE_BINARY);
................................................................................
   280    290     int fIncludeBinary,       /* Include binary files for external diff */
   281    291     u64 diffFlags,            /* Diff control flags */
   282    292     const char *zFileTreeName
   283    293   ){
   284    294     Blob fname;
   285    295     Blob content;
   286    296     int isLink;
   287         -  int isBin;
          297  +  int eType = 0;
   288    298     file_tree_name(zFileTreeName, &fname, 1);
   289    299     historical_version_of_file(zFrom, blob_str(&fname), &content, &isLink, 0,
   290         -                             fIncludeBinary ? 0 : &isBin, 0);
          300  +                             fIncludeBinary ? 0 : &eType, 0);
   291    301     if( !isLink != !file_wd_islink(zFrom) ){
   292    302       fossil_print(DIFF_CANNOT_COMPUTE_SYMLINK);
   293    303     }else{
   294         -    diff_file(&content, isBin, zFileTreeName, zFileTreeName,
          304  +    diff_file(&content, eType, zFileTreeName, zFileTreeName,
   295    305                 zDiffCmd, zBinGlob, fIncludeBinary, diffFlags);
   296    306     }
   297    307     blob_reset(&content);
   298    308     blob_reset(&fname);
   299    309   }
   300    310   
   301    311   /*
................................................................................
   387    397       }else if( isChnged==3 ){
   388    398         fossil_print("ADDED_BY_MERGE %s\n", zPathname);
   389    399         srcid = 0;
   390    400         if( !asNewFile ){ showDiff = 0; }
   391    401       }
   392    402       if( showDiff ){
   393    403         Blob content;
   394         -      int isBin;
          404  +      int eType = 0;
   395    405         if( !isLink != !file_wd_islink(zFullName) ){
   396    406           diff_print_index(zPathname, diffFlags);
   397    407           diff_print_filenames(zPathname, zPathname, diffFlags);
   398    408           fossil_print(DIFF_CANNOT_COMPUTE_SYMLINK);
   399    409           continue;
   400    410         }
   401    411         if( srcid>0 ){
   402    412           content_get(srcid, &content);
   403    413         }else{
   404    414           blob_zero(&content);
   405    415         }
   406         -      isBin = fIncludeBinary ? 0 : looks_like_binary(&content);
          416  +      if( !fIncludeBinary ){
          417  +        eType = looks_like_text(&content);
          418  +      }
   407    419         diff_print_index(zPathname, diffFlags);
   408         -      diff_file(&content, isBin, zFullName, zPathname, zDiffCmd,
          420  +      diff_file(&content, eType, zFullName, zPathname, zDiffCmd,
   409    421                   zBinGlob, fIncludeBinary, diffFlags);
   410    422         blob_reset(&content);
   411    423       }
   412    424       free(zToFree);
   413    425     }
   414    426     db_finalize(&q);
   415    427     db_end_transaction(1);  /* ROLLBACK */
................................................................................
   435    447     u64 diffFlags,
   436    448     const char *zFileTreeName
   437    449   ){
   438    450     char *zName;
   439    451     Blob fname;
   440    452     Blob v1, v2;
   441    453     int isLink1, isLink2;
   442         -  int isBin1, isBin2;
          454  +  int eType = 0, eType2 = 0;
   443    455     if( diffFlags & DIFF_BRIEF ) return;
   444    456     file_tree_name(zFileTreeName, &fname, 1);
   445    457     zName = blob_str(&fname);
   446    458     historical_version_of_file(zFrom, zName, &v1, &isLink1, 0,
   447         -                             fIncludeBinary ? 0 : &isBin1, 0);
          459  +                             fIncludeBinary ? 0 : &eType, 0);
   448    460     historical_version_of_file(zTo, zName, &v2, &isLink2, 0,
   449         -                             fIncludeBinary ? 0 : &isBin2, 0);
          461  +                             fIncludeBinary ? 0 : &eType2, 0);
   450    462     if( isLink1 != isLink2 ){
   451    463       diff_print_filenames(zName, zName, diffFlags);
   452    464       fossil_print(DIFF_CANNOT_COMPUTE_SYMLINK);
          465  +  }else if( eType!=eType2 ){
          466  +    diff_print_filenames(zName, zName, diffFlags);
          467  +    fossil_print(DIFF_CANNOT_COMPUTE_ENCODING);
   453    468     }else{
   454         -    diff_file_mem(&v1, &v2, isBin1, isBin2, zName, zDiffCmd,
          469  +    diff_file_mem(&v1, &v2, eType, zName, zDiffCmd,
   455    470                     zBinGlob, fIncludeBinary, diffFlags);
   456    471     }
   457    472     blob_reset(&v1);
   458    473     blob_reset(&v2);
   459    474     blob_reset(&fname);
   460    475   }
   461    476   
................................................................................
   475    490     struct ManifestFile *pTo,
   476    491     const char *zDiffCmd,
   477    492     const char *zBinGlob,
   478    493     int fIncludeBinary,
   479    494     u64 diffFlags
   480    495   ){
   481    496     Blob f1, f2;
   482         -  int isBin1, isBin2;
          497  +  int eType = 0, eType2 = 0;
   483    498     int rid;
   484    499     const char *zName =  pFrom ? pFrom->zName : pTo->zName;
   485    500     if( diffFlags & DIFF_BRIEF ) return;
   486    501     diff_print_index(zName, diffFlags);
   487    502     if( pFrom ){
   488    503       rid = uuid_to_rid(pFrom->zUuid, 0);
   489    504       content_get(rid, &f1);
................................................................................
   492    507     }
   493    508     if( pTo ){
   494    509       rid = uuid_to_rid(pTo->zUuid, 0);
   495    510       content_get(rid, &f2);
   496    511     }else{
   497    512       blob_zero(&f2);
   498    513     }
   499         -  isBin1 = fIncludeBinary ? 0 : looks_like_binary(&f1);
   500         -  isBin2 = fIncludeBinary ? 0 : looks_like_binary(&f2);
   501         -  diff_file_mem(&f1, &f2, isBin1, isBin2, zName, zDiffCmd,
   502         -                zBinGlob, fIncludeBinary, diffFlags);
          514  +  if ( !fIncludeBinary ){
          515  +    eType = looks_like_text(&f1);
          516  +    eType2 = looks_like_text(&f2);
          517  +  }
          518  +  if( eType!=eType2 ){
          519  +    diff_print_filenames(zName, zName, diffFlags);
          520  +    fossil_print(DIFF_CANNOT_COMPUTE_ENCODING);
          521  +  }else{
          522  +    diff_file_mem(&f1, &f2, eType, zName, zDiffCmd,
          523  +                  zBinGlob, fIncludeBinary, diffFlags);
          524  +  }
   503    525     blob_reset(&f1);
   504    526     blob_reset(&f2);
   505    527   }
   506    528   
   507    529   /*
   508    530   ** Output the differences between two check-ins.
   509    531   **

Changes to src/stash.c.

   304    304        "  FROM stashfile WHERE stashid=%d",
   305    305        stashid
   306    306     );
   307    307     while( db_step(&q)==SQLITE_ROW ){
   308    308       int rid = db_column_int(&q, 0);
   309    309       int isRemoved = db_column_int(&q, 1);
   310    310       int isLink = db_column_int(&q, 3);
   311         -    int isBin1, isBin2;
          311  +    int eType = 0;
   312    312       const char *zOrig = db_column_text(&q, 4);
   313    313       const char *zNew = db_column_text(&q, 5);
   314    314       char *zOPath = mprintf("%s%s", g.zLocalRoot, zOrig);
   315    315       Blob delta, a, b, disk;
   316    316       if( rid==0 ){
   317    317         db_ephemeral_blob(&q, 6, &a);
   318    318         fossil_print("ADDED %s\n", zNew);
   319    319         diff_print_index(zNew, diffFlags);
   320         -      isBin1 = 0;
   321         -      isBin2 = fIncludeBinary ? 0 : looks_like_binary(&a);
   322         -      diff_file_mem(&empty, &a, isBin1, isBin2, zNew, zDiffCmd,
          320  +      if( !fIncludeBinary ){
          321  +        eType = looks_like_text(&a);
          322  +      }
          323  +      diff_file_mem(&empty, &a, eType, zNew, zDiffCmd,
   323    324                       zBinGlob, fIncludeBinary, diffFlags);
   324    325       }else if( isRemoved ){
   325    326         fossil_print("DELETE %s\n", zOrig);
   326    327         if( fBaseline==0 ){
   327    328           if( file_wd_islink(zOPath) ){
   328    329             blob_read_link(&a, zOPath);
   329    330           }else{
   330    331             blob_read_from_file(&a, zOPath);
   331    332           }
   332    333         }else{
   333    334           content_get(rid, &a);
   334    335         }
   335    336         diff_print_index(zNew, diffFlags);
   336         -      isBin1 = fIncludeBinary ? 0 : looks_like_binary(&a);
   337         -      isBin2 = 0;
   338         -      diff_file_mem(&a, &empty, isBin1, isBin2, zOrig, zDiffCmd,
          337  +      if( !fIncludeBinary){
          338  +        eType = looks_like_text(&a);
          339  +      }
          340  +      diff_file_mem(&a, &empty, eType, zOrig, zDiffCmd,
   339    341                       zBinGlob, fIncludeBinary, diffFlags);
   340    342       }else{
   341    343         int isOrigLink = file_wd_islink(zOPath);
   342    344         db_ephemeral_blob(&q, 6, &delta);
   343    345         if( fBaseline==0 ){
   344    346           if( isOrigLink ){
   345    347             blob_read_link(&disk, zOPath);
................................................................................
   352    354           diff_print_index(zNew, diffFlags);
   353    355           diff_print_filenames(zOrig, zNew, diffFlags);
   354    356           printf(DIFF_CANNOT_COMPUTE_SYMLINK);
   355    357         }else{
   356    358           Blob *pBase = fBaseline ? &a : &disk;
   357    359           content_get(rid, &a);
   358    360           blob_delta_apply(&a, &delta, &b);
   359         -        isBin1 = fIncludeBinary ? 0 : looks_like_binary(pBase);
   360         -        isBin2 = fIncludeBinary ? 0 : looks_like_binary(&b);
   361         -        diff_file_mem(fBaseline? &a : &disk, &b, isBin1, isBin2, zNew,
   362         -                      zDiffCmd, zBinGlob, fIncludeBinary, diffFlags);
          361  +        int eType2 = 0;
          362  +        if( !fIncludeBinary ){
          363  +          eType = looks_like_text(pBase);
          364  +          eType2 = looks_like_text(&b);
          365  +        }
          366  +        if( eType!=eType2 ){
          367  +          diff_print_filenames(zOrig, zNew, diffFlags);
          368  +          printf(DIFF_CANNOT_COMPUTE_ENCODING);
          369  +        }else{
          370  +          diff_file_mem(pBase, &b, eType, zNew, zDiffCmd,
          371  +                        zBinGlob, fIncludeBinary, diffFlags);
          372  +        }
   363    373           blob_reset(&a);
   364    374           blob_reset(&b);
   365    375         }
   366    376         if( !fBaseline ) blob_reset(&disk);
   367    377       }
   368    378       blob_reset(&delta);
   369         - }
          379  +  }
   370    380     db_finalize(&q);
   371    381   }
   372    382   
   373    383   /*
   374    384   ** Drop the indicated stash
   375    385   */
   376    386   static void stash_drop(int stashid){

Changes to src/update.c.

   598    598   */
   599    599   int historical_version_of_file(
   600    600     const char *revision,    /* The checkin containing the file */
   601    601     const char *file,        /* Full treename of the file */
   602    602     Blob *content,           /* Put the content here */
   603    603     int *pIsLink,            /* Set to true if file is link. */
   604    604     int *pIsExe,             /* Set to true if file is executable */
   605         -  int *pIsBin,             /* Set to true if file is binary */
          605  +  int *pEType,             /* Set to file type, look_like_text()&3 */
   606    606     int errCode              /* Error code if file not found.  Panic if 0. */
   607    607   ){
   608    608     Manifest *pManifest;
   609    609     ManifestFile *pFile;
   610    610     int rid=0;
   611    611     
   612    612     if( revision ){
................................................................................
   625    625       if( pFile ){
   626    626         int rc;
   627    627         rid = uuid_to_rid(pFile->zUuid, 0);
   628    628         if( pIsExe ) *pIsExe = ( manifest_file_mperm(pFile)==PERM_EXE );
   629    629         if( pIsLink ) *pIsLink = ( manifest_file_mperm(pFile)==PERM_LNK );
   630    630         manifest_destroy(pManifest);
   631    631         rc = content_get(rid, content);
   632         -      if( rc && pIsBin ){
   633         -        *pIsBin = looks_like_binary(content);
          632  +      if( rc && pEType ){
          633  +        *pEType = looks_like_text(content);
   634    634         }
   635    635         return rc;
   636    636       }
   637    637       manifest_destroy(pManifest);
   638    638       if( errCode<=0 ){
   639    639         fossil_fatal("file %s does not exist in checkin: %s", file, revision);
   640    640       }