Fossil SCM
Give the user the option to convert file into UTF8 if they are in some other encoding when committed. The commit aborts regardless, to give the operator an opporunity to retest the changes before committing again.
Commit
22b570f4f33e1d9ba32d0eddc47c5fed7fabc0bd
Parent
fcdeaa29098ade4…
2 files changed
+39
-10
+39
-10
+39
-10
| --- src/checkin.c | ||
| +++ src/checkin.c | ||
| @@ -886,13 +886,17 @@ | ||
| 886 | 886 | |
| 887 | 887 | /* |
| 888 | 888 | ** Issue a warning and give the user an opportunity to abandon out |
| 889 | 889 | ** if a Unicode (UTF-16) byte-order-mark (BOM) or a \r\n line ending |
| 890 | 890 | ** is seen in a text file. |
| 891 | +** | |
| 892 | +** Return 1 if the user pressed 'c'. In that case, the file will have | |
| 893 | +** been converted to UTF-8 (if it was UTF-16) with NL line-endings, | |
| 894 | +** and the original file will have been renamed to "<filename>-original". | |
| 891 | 895 | */ |
| 892 | -static void commit_warning( | |
| 893 | - const Blob *p, /* The content of the file being committed. */ | |
| 896 | +static int commit_warning( | |
| 897 | + Blob *p, /* The content of the file being committed. */ | |
| 894 | 898 | int crnlOk, /* Non-zero if CR/NL warnings should be disabled. */ |
| 895 | 899 | int binOk, /* Non-zero if binary warnings should be disabled. */ |
| 896 | 900 | int unicodeOk, /* Non-zero if unicode warnings should be disabled. */ |
| 897 | 901 | const char *zFilename /* The full name of the file being committed. */ |
| 898 | 902 | ){ |
| @@ -900,56 +904,78 @@ | ||
| 900 | 904 | int fUnicode; /* return value of starts_with_utf16_bom() */ |
| 901 | 905 | char *zMsg; /* Warning message */ |
| 902 | 906 | Blob fname; /* Relative pathname of the file */ |
| 903 | 907 | static int allOk = 0; /* Set to true to disable this routine */ |
| 904 | 908 | |
| 905 | - if( allOk ) return; | |
| 909 | + if( allOk ) return 0; | |
| 906 | 910 | fUnicode = starts_with_utf16_bom(p, 0); |
| 907 | 911 | eType = fUnicode ? looks_like_utf16(p) : looks_like_utf8(p); |
| 908 | 912 | if( eType==0 || eType==-1 || fUnicode ){ |
| 909 | 913 | const char *zWarning; |
| 914 | + const char *zConvert = "c=convert/"; | |
| 910 | 915 | Blob ans; |
| 911 | 916 | char cReply; |
| 912 | 917 | |
| 913 | 918 | if( eType==-1 && fUnicode ){ |
| 914 | 919 | if ( crnlOk && unicodeOk ){ |
| 915 | - return; /* We don't want Unicode/CR/NL warnings for this file. */ | |
| 920 | + return 0; /* We don't want Unicode/CR/NL warnings for this file. */ | |
| 916 | 921 | } |
| 917 | 922 | zWarning = "Unicode and CR/NL line endings"; |
| 918 | 923 | }else if( eType==-1 ){ |
| 919 | 924 | if( crnlOk ){ |
| 920 | - return; /* We don't want CR/NL warnings for this file. */ | |
| 925 | + return 0; /* We don't want CR/NL warnings for this file. */ | |
| 921 | 926 | } |
| 922 | 927 | zWarning = "CR/NL line endings"; |
| 923 | 928 | }else if( eType==0 ){ |
| 924 | 929 | if( binOk ){ |
| 925 | - return; /* We don't want binary warnings for this file. */ | |
| 930 | + return 0; /* We don't want binary warnings for this file. */ | |
| 926 | 931 | } |
| 927 | 932 | zWarning = "binary data"; |
| 933 | + zConvert = ""; /* We cannot convert binary files. */ | |
| 928 | 934 | }else{ |
| 929 | 935 | if ( unicodeOk ){ |
| 930 | - return; /* We don't want unicode warnings for this file. */ | |
| 936 | + return 0; /* We don't want unicode warnings for this file. */ | |
| 931 | 937 | } |
| 932 | 938 | zWarning = "Unicode"; |
| 939 | +#ifndef _WIN32 | |
| 940 | + zConvert = ""; /* On Unix, we cannot easily convert Unicode files. */ | |
| 941 | +#endif | |
| 933 | 942 | } |
| 934 | 943 | file_relative_name(zFilename, &fname, 0); |
| 935 | 944 | blob_zero(&ans); |
| 936 | 945 | zMsg = mprintf( |
| 937 | - "%s contains %s. commit anyhow (a=all/y/N)? ", | |
| 938 | - blob_str(&fname), zWarning); | |
| 946 | + "%s contains %s. commit anyhow (a=all/%sy/N)? ", | |
| 947 | + blob_str(&fname), zWarning, zConvert); | |
| 939 | 948 | prompt_user(zMsg, &ans); |
| 940 | 949 | fossil_free(zMsg); |
| 941 | 950 | cReply = blob_str(&ans)[0]; |
| 942 | 951 | if( cReply=='a' || cReply=='A' ){ |
| 943 | 952 | allOk = 1; |
| 953 | + }else if( *zConvert && (cReply=='c' || cReply=='C') ){ | |
| 954 | + char *zOrig = file_newname(zFilename, "original", 1); | |
| 955 | + FILE *f; | |
| 956 | + blob_write_to_file(p, zOrig); | |
| 957 | + fossil_free(zOrig); | |
| 958 | + f = fossil_fopen(zFilename, "wb"); | |
| 959 | + if( fUnicode ) { | |
| 960 | + int bomSize; | |
| 961 | + const unsigned char *bom = get_utf8_bom(&bomSize); | |
| 962 | + fwrite(bom, 1, bomSize, f); | |
| 963 | + blob_to_utf8_no_bom(p, 0); | |
| 964 | + } | |
| 965 | + blob_remove_cr(p); | |
| 966 | + fwrite(blob_buffer(p), 1, blob_size(p), f); | |
| 967 | + fclose(f); | |
| 968 | + return 1; | |
| 944 | 969 | }else if( cReply!='y' && cReply!='Y' ){ |
| 945 | 970 | fossil_fatal("Abandoning commit due to %s in %s", |
| 946 | 971 | zWarning, blob_str(&fname)); |
| 947 | 972 | } |
| 948 | 973 | blob_reset(&ans); |
| 949 | 974 | blob_reset(&fname); |
| 950 | 975 | } |
| 976 | + return 0; | |
| 951 | 977 | } |
| 952 | 978 | |
| 953 | 979 | /* |
| 954 | 980 | ** qsort() comparison routine for an array of pointers to strings. |
| 955 | 981 | */ |
| @@ -1065,10 +1091,11 @@ | ||
| 1065 | 1091 | Blob cksum1, cksum2; /* Before and after commit checksums */ |
| 1066 | 1092 | Blob cksum1b; /* Checksum recorded in the manifest */ |
| 1067 | 1093 | int szD; /* Size of the delta manifest */ |
| 1068 | 1094 | int szB; /* Size of the baseline manifest */ |
| 1069 | 1095 | int nConflict = 0; /* Number of unresolved merge conflicts */ |
| 1096 | + int abortCommit = 0; | |
| 1070 | 1097 | Blob ans; |
| 1071 | 1098 | char cReply; |
| 1072 | 1099 | |
| 1073 | 1100 | url_proxy_options(); |
| 1074 | 1101 | noSign = find_option("nosign",0,0)!=0; |
| @@ -1312,11 +1339,11 @@ | ||
| 1312 | 1339 | }else{ |
| 1313 | 1340 | blob_read_from_file(&content, zFullname); |
| 1314 | 1341 | } |
| 1315 | 1342 | /* Do not emit any warnings when they are disabled. */ |
| 1316 | 1343 | if( !noWarningFlag ){ |
| 1317 | - commit_warning(&content, crnlOk, binOk, unicodeOk, zFullname); | |
| 1344 | + abortCommit |= commit_warning(&content, crnlOk, binOk, unicodeOk, zFullname); | |
| 1318 | 1345 | } |
| 1319 | 1346 | if( chnged==1 && contains_merge_marker(&content) ){ |
| 1320 | 1347 | Blob fname; /* Relative pathname of the file */ |
| 1321 | 1348 | |
| 1322 | 1349 | nConflict++; |
| @@ -1335,10 +1362,12 @@ | ||
| 1335 | 1362 | } |
| 1336 | 1363 | db_finalize(&q); |
| 1337 | 1364 | if( nConflict && !allowConflict ){ |
| 1338 | 1365 | fossil_fatal("abort due to unresolved merge conflicts; " |
| 1339 | 1366 | "use --allow-conflict to override"); |
| 1367 | + } else if( abortCommit ){ | |
| 1368 | + fossil_fatal("files are converted on your request. Please re-test before committing"); | |
| 1340 | 1369 | } |
| 1341 | 1370 | |
| 1342 | 1371 | /* Create the new manifest */ |
| 1343 | 1372 | if( blob_size(&comment)==0 ){ |
| 1344 | 1373 | blob_append(&comment, "(no comment)", -1); |
| 1345 | 1374 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -886,13 +886,17 @@ | |
| 886 | |
| 887 | /* |
| 888 | ** Issue a warning and give the user an opportunity to abandon out |
| 889 | ** if a Unicode (UTF-16) byte-order-mark (BOM) or a \r\n line ending |
| 890 | ** is seen in a text file. |
| 891 | */ |
| 892 | static void commit_warning( |
| 893 | const Blob *p, /* The content of the file being committed. */ |
| 894 | int crnlOk, /* Non-zero if CR/NL warnings should be disabled. */ |
| 895 | int binOk, /* Non-zero if binary warnings should be disabled. */ |
| 896 | int unicodeOk, /* Non-zero if unicode warnings should be disabled. */ |
| 897 | const char *zFilename /* The full name of the file being committed. */ |
| 898 | ){ |
| @@ -900,56 +904,78 @@ | |
| 900 | int fUnicode; /* return value of starts_with_utf16_bom() */ |
| 901 | char *zMsg; /* Warning message */ |
| 902 | Blob fname; /* Relative pathname of the file */ |
| 903 | static int allOk = 0; /* Set to true to disable this routine */ |
| 904 | |
| 905 | if( allOk ) return; |
| 906 | fUnicode = starts_with_utf16_bom(p, 0); |
| 907 | eType = fUnicode ? looks_like_utf16(p) : looks_like_utf8(p); |
| 908 | if( eType==0 || eType==-1 || fUnicode ){ |
| 909 | const char *zWarning; |
| 910 | Blob ans; |
| 911 | char cReply; |
| 912 | |
| 913 | if( eType==-1 && fUnicode ){ |
| 914 | if ( crnlOk && unicodeOk ){ |
| 915 | return; /* We don't want Unicode/CR/NL warnings for this file. */ |
| 916 | } |
| 917 | zWarning = "Unicode and CR/NL line endings"; |
| 918 | }else if( eType==-1 ){ |
| 919 | if( crnlOk ){ |
| 920 | return; /* We don't want CR/NL warnings for this file. */ |
| 921 | } |
| 922 | zWarning = "CR/NL line endings"; |
| 923 | }else if( eType==0 ){ |
| 924 | if( binOk ){ |
| 925 | return; /* We don't want binary warnings for this file. */ |
| 926 | } |
| 927 | zWarning = "binary data"; |
| 928 | }else{ |
| 929 | if ( unicodeOk ){ |
| 930 | return; /* We don't want unicode warnings for this file. */ |
| 931 | } |
| 932 | zWarning = "Unicode"; |
| 933 | } |
| 934 | file_relative_name(zFilename, &fname, 0); |
| 935 | blob_zero(&ans); |
| 936 | zMsg = mprintf( |
| 937 | "%s contains %s. commit anyhow (a=all/y/N)? ", |
| 938 | blob_str(&fname), zWarning); |
| 939 | prompt_user(zMsg, &ans); |
| 940 | fossil_free(zMsg); |
| 941 | cReply = blob_str(&ans)[0]; |
| 942 | if( cReply=='a' || cReply=='A' ){ |
| 943 | allOk = 1; |
| 944 | }else if( cReply!='y' && cReply!='Y' ){ |
| 945 | fossil_fatal("Abandoning commit due to %s in %s", |
| 946 | zWarning, blob_str(&fname)); |
| 947 | } |
| 948 | blob_reset(&ans); |
| 949 | blob_reset(&fname); |
| 950 | } |
| 951 | } |
| 952 | |
| 953 | /* |
| 954 | ** qsort() comparison routine for an array of pointers to strings. |
| 955 | */ |
| @@ -1065,10 +1091,11 @@ | |
| 1065 | Blob cksum1, cksum2; /* Before and after commit checksums */ |
| 1066 | Blob cksum1b; /* Checksum recorded in the manifest */ |
| 1067 | int szD; /* Size of the delta manifest */ |
| 1068 | int szB; /* Size of the baseline manifest */ |
| 1069 | int nConflict = 0; /* Number of unresolved merge conflicts */ |
| 1070 | Blob ans; |
| 1071 | char cReply; |
| 1072 | |
| 1073 | url_proxy_options(); |
| 1074 | noSign = find_option("nosign",0,0)!=0; |
| @@ -1312,11 +1339,11 @@ | |
| 1312 | }else{ |
| 1313 | blob_read_from_file(&content, zFullname); |
| 1314 | } |
| 1315 | /* Do not emit any warnings when they are disabled. */ |
| 1316 | if( !noWarningFlag ){ |
| 1317 | commit_warning(&content, crnlOk, binOk, unicodeOk, zFullname); |
| 1318 | } |
| 1319 | if( chnged==1 && contains_merge_marker(&content) ){ |
| 1320 | Blob fname; /* Relative pathname of the file */ |
| 1321 | |
| 1322 | nConflict++; |
| @@ -1335,10 +1362,12 @@ | |
| 1335 | } |
| 1336 | db_finalize(&q); |
| 1337 | if( nConflict && !allowConflict ){ |
| 1338 | fossil_fatal("abort due to unresolved merge conflicts; " |
| 1339 | "use --allow-conflict to override"); |
| 1340 | } |
| 1341 | |
| 1342 | /* Create the new manifest */ |
| 1343 | if( blob_size(&comment)==0 ){ |
| 1344 | blob_append(&comment, "(no comment)", -1); |
| 1345 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -886,13 +886,17 @@ | |
| 886 | |
| 887 | /* |
| 888 | ** Issue a warning and give the user an opportunity to abandon out |
| 889 | ** if a Unicode (UTF-16) byte-order-mark (BOM) or a \r\n line ending |
| 890 | ** is seen in a text file. |
| 891 | ** |
| 892 | ** Return 1 if the user pressed 'c'. In that case, the file will have |
| 893 | ** been converted to UTF-8 (if it was UTF-16) with NL line-endings, |
| 894 | ** and the original file will have been renamed to "<filename>-original". |
| 895 | */ |
| 896 | static int commit_warning( |
| 897 | Blob *p, /* The content of the file being committed. */ |
| 898 | int crnlOk, /* Non-zero if CR/NL warnings should be disabled. */ |
| 899 | int binOk, /* Non-zero if binary warnings should be disabled. */ |
| 900 | int unicodeOk, /* Non-zero if unicode warnings should be disabled. */ |
| 901 | const char *zFilename /* The full name of the file being committed. */ |
| 902 | ){ |
| @@ -900,56 +904,78 @@ | |
| 904 | int fUnicode; /* return value of starts_with_utf16_bom() */ |
| 905 | char *zMsg; /* Warning message */ |
| 906 | Blob fname; /* Relative pathname of the file */ |
| 907 | static int allOk = 0; /* Set to true to disable this routine */ |
| 908 | |
| 909 | if( allOk ) return 0; |
| 910 | fUnicode = starts_with_utf16_bom(p, 0); |
| 911 | eType = fUnicode ? looks_like_utf16(p) : looks_like_utf8(p); |
| 912 | if( eType==0 || eType==-1 || fUnicode ){ |
| 913 | const char *zWarning; |
| 914 | const char *zConvert = "c=convert/"; |
| 915 | Blob ans; |
| 916 | char cReply; |
| 917 | |
| 918 | if( eType==-1 && fUnicode ){ |
| 919 | if ( crnlOk && unicodeOk ){ |
| 920 | return 0; /* We don't want Unicode/CR/NL warnings for this file. */ |
| 921 | } |
| 922 | zWarning = "Unicode and CR/NL line endings"; |
| 923 | }else if( eType==-1 ){ |
| 924 | if( crnlOk ){ |
| 925 | return 0; /* We don't want CR/NL warnings for this file. */ |
| 926 | } |
| 927 | zWarning = "CR/NL line endings"; |
| 928 | }else if( eType==0 ){ |
| 929 | if( binOk ){ |
| 930 | return 0; /* We don't want binary warnings for this file. */ |
| 931 | } |
| 932 | zWarning = "binary data"; |
| 933 | zConvert = ""; /* We cannot convert binary files. */ |
| 934 | }else{ |
| 935 | if ( unicodeOk ){ |
| 936 | return 0; /* We don't want unicode warnings for this file. */ |
| 937 | } |
| 938 | zWarning = "Unicode"; |
| 939 | #ifndef _WIN32 |
| 940 | zConvert = ""; /* On Unix, we cannot easily convert Unicode files. */ |
| 941 | #endif |
| 942 | } |
| 943 | file_relative_name(zFilename, &fname, 0); |
| 944 | blob_zero(&ans); |
| 945 | zMsg = mprintf( |
| 946 | "%s contains %s. commit anyhow (a=all/%sy/N)? ", |
| 947 | blob_str(&fname), zWarning, zConvert); |
| 948 | prompt_user(zMsg, &ans); |
| 949 | fossil_free(zMsg); |
| 950 | cReply = blob_str(&ans)[0]; |
| 951 | if( cReply=='a' || cReply=='A' ){ |
| 952 | allOk = 1; |
| 953 | }else if( *zConvert && (cReply=='c' || cReply=='C') ){ |
| 954 | char *zOrig = file_newname(zFilename, "original", 1); |
| 955 | FILE *f; |
| 956 | blob_write_to_file(p, zOrig); |
| 957 | fossil_free(zOrig); |
| 958 | f = fossil_fopen(zFilename, "wb"); |
| 959 | if( fUnicode ) { |
| 960 | int bomSize; |
| 961 | const unsigned char *bom = get_utf8_bom(&bomSize); |
| 962 | fwrite(bom, 1, bomSize, f); |
| 963 | blob_to_utf8_no_bom(p, 0); |
| 964 | } |
| 965 | blob_remove_cr(p); |
| 966 | fwrite(blob_buffer(p), 1, blob_size(p), f); |
| 967 | fclose(f); |
| 968 | return 1; |
| 969 | }else if( cReply!='y' && cReply!='Y' ){ |
| 970 | fossil_fatal("Abandoning commit due to %s in %s", |
| 971 | zWarning, blob_str(&fname)); |
| 972 | } |
| 973 | blob_reset(&ans); |
| 974 | blob_reset(&fname); |
| 975 | } |
| 976 | return 0; |
| 977 | } |
| 978 | |
| 979 | /* |
| 980 | ** qsort() comparison routine for an array of pointers to strings. |
| 981 | */ |
| @@ -1065,10 +1091,11 @@ | |
| 1091 | Blob cksum1, cksum2; /* Before and after commit checksums */ |
| 1092 | Blob cksum1b; /* Checksum recorded in the manifest */ |
| 1093 | int szD; /* Size of the delta manifest */ |
| 1094 | int szB; /* Size of the baseline manifest */ |
| 1095 | int nConflict = 0; /* Number of unresolved merge conflicts */ |
| 1096 | int abortCommit = 0; |
| 1097 | Blob ans; |
| 1098 | char cReply; |
| 1099 | |
| 1100 | url_proxy_options(); |
| 1101 | noSign = find_option("nosign",0,0)!=0; |
| @@ -1312,11 +1339,11 @@ | |
| 1339 | }else{ |
| 1340 | blob_read_from_file(&content, zFullname); |
| 1341 | } |
| 1342 | /* Do not emit any warnings when they are disabled. */ |
| 1343 | if( !noWarningFlag ){ |
| 1344 | abortCommit |= commit_warning(&content, crnlOk, binOk, unicodeOk, zFullname); |
| 1345 | } |
| 1346 | if( chnged==1 && contains_merge_marker(&content) ){ |
| 1347 | Blob fname; /* Relative pathname of the file */ |
| 1348 | |
| 1349 | nConflict++; |
| @@ -1335,10 +1362,12 @@ | |
| 1362 | } |
| 1363 | db_finalize(&q); |
| 1364 | if( nConflict && !allowConflict ){ |
| 1365 | fossil_fatal("abort due to unresolved merge conflicts; " |
| 1366 | "use --allow-conflict to override"); |
| 1367 | } else if( abortCommit ){ |
| 1368 | fossil_fatal("files are converted on your request. Please re-test before committing"); |
| 1369 | } |
| 1370 | |
| 1371 | /* Create the new manifest */ |
| 1372 | if( blob_size(&comment)==0 ){ |
| 1373 | blob_append(&comment, "(no comment)", -1); |
| 1374 |
+39
-10
| --- src/checkin.c | ||
| +++ src/checkin.c | ||
| @@ -886,13 +886,17 @@ | ||
| 886 | 886 | |
| 887 | 887 | /* |
| 888 | 888 | ** Issue a warning and give the user an opportunity to abandon out |
| 889 | 889 | ** if a Unicode (UTF-16) byte-order-mark (BOM) or a \r\n line ending |
| 890 | 890 | ** is seen in a text file. |
| 891 | +** | |
| 892 | +** Return 1 if the user pressed 'c'. In that case, the file will have | |
| 893 | +** been converted to UTF-8 (if it was UTF-16) with NL line-endings, | |
| 894 | +** and the original file will have been renamed to "<filename>-original". | |
| 891 | 895 | */ |
| 892 | -static void commit_warning( | |
| 893 | - const Blob *p, /* The content of the file being committed. */ | |
| 896 | +static int commit_warning( | |
| 897 | + Blob *p, /* The content of the file being committed. */ | |
| 894 | 898 | int crnlOk, /* Non-zero if CR/NL warnings should be disabled. */ |
| 895 | 899 | int binOk, /* Non-zero if binary warnings should be disabled. */ |
| 896 | 900 | int unicodeOk, /* Non-zero if unicode warnings should be disabled. */ |
| 897 | 901 | const char *zFilename /* The full name of the file being committed. */ |
| 898 | 902 | ){ |
| @@ -900,56 +904,78 @@ | ||
| 900 | 904 | int fUnicode; /* return value of starts_with_utf16_bom() */ |
| 901 | 905 | char *zMsg; /* Warning message */ |
| 902 | 906 | Blob fname; /* Relative pathname of the file */ |
| 903 | 907 | static int allOk = 0; /* Set to true to disable this routine */ |
| 904 | 908 | |
| 905 | - if( allOk ) return; | |
| 909 | + if( allOk ) return 0; | |
| 906 | 910 | fUnicode = starts_with_utf16_bom(p, 0); |
| 907 | 911 | eType = fUnicode ? looks_like_utf16(p) : looks_like_utf8(p); |
| 908 | 912 | if( eType==0 || eType==-1 || fUnicode ){ |
| 909 | 913 | const char *zWarning; |
| 914 | + const char *zConvert = "c=convert/"; | |
| 910 | 915 | Blob ans; |
| 911 | 916 | char cReply; |
| 912 | 917 | |
| 913 | 918 | if( eType==-1 && fUnicode ){ |
| 914 | 919 | if ( crnlOk && unicodeOk ){ |
| 915 | - return; /* We don't want Unicode/CR/NL warnings for this file. */ | |
| 920 | + return 0; /* We don't want Unicode/CR/NL warnings for this file. */ | |
| 916 | 921 | } |
| 917 | 922 | zWarning = "Unicode and CR/NL line endings"; |
| 918 | 923 | }else if( eType==-1 ){ |
| 919 | 924 | if( crnlOk ){ |
| 920 | - return; /* We don't want CR/NL warnings for this file. */ | |
| 925 | + return 0; /* We don't want CR/NL warnings for this file. */ | |
| 921 | 926 | } |
| 922 | 927 | zWarning = "CR/NL line endings"; |
| 923 | 928 | }else if( eType==0 ){ |
| 924 | 929 | if( binOk ){ |
| 925 | - return; /* We don't want binary warnings for this file. */ | |
| 930 | + return 0; /* We don't want binary warnings for this file. */ | |
| 926 | 931 | } |
| 927 | 932 | zWarning = "binary data"; |
| 933 | + zConvert = ""; /* We cannot convert binary files. */ | |
| 928 | 934 | }else{ |
| 929 | 935 | if ( unicodeOk ){ |
| 930 | - return; /* We don't want unicode warnings for this file. */ | |
| 936 | + return 0; /* We don't want unicode warnings for this file. */ | |
| 931 | 937 | } |
| 932 | 938 | zWarning = "Unicode"; |
| 939 | +#ifndef _WIN32 | |
| 940 | + zConvert = ""; /* On Unix, we cannot easily convert Unicode files. */ | |
| 941 | +#endif | |
| 933 | 942 | } |
| 934 | 943 | file_relative_name(zFilename, &fname, 0); |
| 935 | 944 | blob_zero(&ans); |
| 936 | 945 | zMsg = mprintf( |
| 937 | - "%s contains %s. commit anyhow (a=all/y/N)? ", | |
| 938 | - blob_str(&fname), zWarning); | |
| 946 | + "%s contains %s. commit anyhow (a=all/%sy/N)? ", | |
| 947 | + blob_str(&fname), zWarning, zConvert); | |
| 939 | 948 | prompt_user(zMsg, &ans); |
| 940 | 949 | fossil_free(zMsg); |
| 941 | 950 | cReply = blob_str(&ans)[0]; |
| 942 | 951 | if( cReply=='a' || cReply=='A' ){ |
| 943 | 952 | allOk = 1; |
| 953 | + }else if( *zConvert && (cReply=='c' || cReply=='C') ){ | |
| 954 | + char *zOrig = file_newname(zFilename, "original", 1); | |
| 955 | + FILE *f; | |
| 956 | + blob_write_to_file(p, zOrig); | |
| 957 | + fossil_free(zOrig); | |
| 958 | + f = fossil_fopen(zFilename, "wb"); | |
| 959 | + if( fUnicode ) { | |
| 960 | + int bomSize; | |
| 961 | + const unsigned char *bom = get_utf8_bom(&bomSize); | |
| 962 | + fwrite(bom, 1, bomSize, f); | |
| 963 | + blob_to_utf8_no_bom(p, 0); | |
| 964 | + } | |
| 965 | + blob_remove_cr(p); | |
| 966 | + fwrite(blob_buffer(p), 1, blob_size(p), f); | |
| 967 | + fclose(f); | |
| 968 | + return 1; | |
| 944 | 969 | }else if( cReply!='y' && cReply!='Y' ){ |
| 945 | 970 | fossil_fatal("Abandoning commit due to %s in %s", |
| 946 | 971 | zWarning, blob_str(&fname)); |
| 947 | 972 | } |
| 948 | 973 | blob_reset(&ans); |
| 949 | 974 | blob_reset(&fname); |
| 950 | 975 | } |
| 976 | + return 0; | |
| 951 | 977 | } |
| 952 | 978 | |
| 953 | 979 | /* |
| 954 | 980 | ** qsort() comparison routine for an array of pointers to strings. |
| 955 | 981 | */ |
| @@ -1065,10 +1091,11 @@ | ||
| 1065 | 1091 | Blob cksum1, cksum2; /* Before and after commit checksums */ |
| 1066 | 1092 | Blob cksum1b; /* Checksum recorded in the manifest */ |
| 1067 | 1093 | int szD; /* Size of the delta manifest */ |
| 1068 | 1094 | int szB; /* Size of the baseline manifest */ |
| 1069 | 1095 | int nConflict = 0; /* Number of unresolved merge conflicts */ |
| 1096 | + int abortCommit = 0; | |
| 1070 | 1097 | Blob ans; |
| 1071 | 1098 | char cReply; |
| 1072 | 1099 | |
| 1073 | 1100 | url_proxy_options(); |
| 1074 | 1101 | noSign = find_option("nosign",0,0)!=0; |
| @@ -1312,11 +1339,11 @@ | ||
| 1312 | 1339 | }else{ |
| 1313 | 1340 | blob_read_from_file(&content, zFullname); |
| 1314 | 1341 | } |
| 1315 | 1342 | /* Do not emit any warnings when they are disabled. */ |
| 1316 | 1343 | if( !noWarningFlag ){ |
| 1317 | - commit_warning(&content, crnlOk, binOk, unicodeOk, zFullname); | |
| 1344 | + abortCommit |= commit_warning(&content, crnlOk, binOk, unicodeOk, zFullname); | |
| 1318 | 1345 | } |
| 1319 | 1346 | if( chnged==1 && contains_merge_marker(&content) ){ |
| 1320 | 1347 | Blob fname; /* Relative pathname of the file */ |
| 1321 | 1348 | |
| 1322 | 1349 | nConflict++; |
| @@ -1335,10 +1362,12 @@ | ||
| 1335 | 1362 | } |
| 1336 | 1363 | db_finalize(&q); |
| 1337 | 1364 | if( nConflict && !allowConflict ){ |
| 1338 | 1365 | fossil_fatal("abort due to unresolved merge conflicts; " |
| 1339 | 1366 | "use --allow-conflict to override"); |
| 1367 | + } else if( abortCommit ){ | |
| 1368 | + fossil_fatal("files are converted on your request. Please re-test before committing"); | |
| 1340 | 1369 | } |
| 1341 | 1370 | |
| 1342 | 1371 | /* Create the new manifest */ |
| 1343 | 1372 | if( blob_size(&comment)==0 ){ |
| 1344 | 1373 | blob_append(&comment, "(no comment)", -1); |
| 1345 | 1374 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -886,13 +886,17 @@ | |
| 886 | |
| 887 | /* |
| 888 | ** Issue a warning and give the user an opportunity to abandon out |
| 889 | ** if a Unicode (UTF-16) byte-order-mark (BOM) or a \r\n line ending |
| 890 | ** is seen in a text file. |
| 891 | */ |
| 892 | static void commit_warning( |
| 893 | const Blob *p, /* The content of the file being committed. */ |
| 894 | int crnlOk, /* Non-zero if CR/NL warnings should be disabled. */ |
| 895 | int binOk, /* Non-zero if binary warnings should be disabled. */ |
| 896 | int unicodeOk, /* Non-zero if unicode warnings should be disabled. */ |
| 897 | const char *zFilename /* The full name of the file being committed. */ |
| 898 | ){ |
| @@ -900,56 +904,78 @@ | |
| 900 | int fUnicode; /* return value of starts_with_utf16_bom() */ |
| 901 | char *zMsg; /* Warning message */ |
| 902 | Blob fname; /* Relative pathname of the file */ |
| 903 | static int allOk = 0; /* Set to true to disable this routine */ |
| 904 | |
| 905 | if( allOk ) return; |
| 906 | fUnicode = starts_with_utf16_bom(p, 0); |
| 907 | eType = fUnicode ? looks_like_utf16(p) : looks_like_utf8(p); |
| 908 | if( eType==0 || eType==-1 || fUnicode ){ |
| 909 | const char *zWarning; |
| 910 | Blob ans; |
| 911 | char cReply; |
| 912 | |
| 913 | if( eType==-1 && fUnicode ){ |
| 914 | if ( crnlOk && unicodeOk ){ |
| 915 | return; /* We don't want Unicode/CR/NL warnings for this file. */ |
| 916 | } |
| 917 | zWarning = "Unicode and CR/NL line endings"; |
| 918 | }else if( eType==-1 ){ |
| 919 | if( crnlOk ){ |
| 920 | return; /* We don't want CR/NL warnings for this file. */ |
| 921 | } |
| 922 | zWarning = "CR/NL line endings"; |
| 923 | }else if( eType==0 ){ |
| 924 | if( binOk ){ |
| 925 | return; /* We don't want binary warnings for this file. */ |
| 926 | } |
| 927 | zWarning = "binary data"; |
| 928 | }else{ |
| 929 | if ( unicodeOk ){ |
| 930 | return; /* We don't want unicode warnings for this file. */ |
| 931 | } |
| 932 | zWarning = "Unicode"; |
| 933 | } |
| 934 | file_relative_name(zFilename, &fname, 0); |
| 935 | blob_zero(&ans); |
| 936 | zMsg = mprintf( |
| 937 | "%s contains %s. commit anyhow (a=all/y/N)? ", |
| 938 | blob_str(&fname), zWarning); |
| 939 | prompt_user(zMsg, &ans); |
| 940 | fossil_free(zMsg); |
| 941 | cReply = blob_str(&ans)[0]; |
| 942 | if( cReply=='a' || cReply=='A' ){ |
| 943 | allOk = 1; |
| 944 | }else if( cReply!='y' && cReply!='Y' ){ |
| 945 | fossil_fatal("Abandoning commit due to %s in %s", |
| 946 | zWarning, blob_str(&fname)); |
| 947 | } |
| 948 | blob_reset(&ans); |
| 949 | blob_reset(&fname); |
| 950 | } |
| 951 | } |
| 952 | |
| 953 | /* |
| 954 | ** qsort() comparison routine for an array of pointers to strings. |
| 955 | */ |
| @@ -1065,10 +1091,11 @@ | |
| 1065 | Blob cksum1, cksum2; /* Before and after commit checksums */ |
| 1066 | Blob cksum1b; /* Checksum recorded in the manifest */ |
| 1067 | int szD; /* Size of the delta manifest */ |
| 1068 | int szB; /* Size of the baseline manifest */ |
| 1069 | int nConflict = 0; /* Number of unresolved merge conflicts */ |
| 1070 | Blob ans; |
| 1071 | char cReply; |
| 1072 | |
| 1073 | url_proxy_options(); |
| 1074 | noSign = find_option("nosign",0,0)!=0; |
| @@ -1312,11 +1339,11 @@ | |
| 1312 | }else{ |
| 1313 | blob_read_from_file(&content, zFullname); |
| 1314 | } |
| 1315 | /* Do not emit any warnings when they are disabled. */ |
| 1316 | if( !noWarningFlag ){ |
| 1317 | commit_warning(&content, crnlOk, binOk, unicodeOk, zFullname); |
| 1318 | } |
| 1319 | if( chnged==1 && contains_merge_marker(&content) ){ |
| 1320 | Blob fname; /* Relative pathname of the file */ |
| 1321 | |
| 1322 | nConflict++; |
| @@ -1335,10 +1362,12 @@ | |
| 1335 | } |
| 1336 | db_finalize(&q); |
| 1337 | if( nConflict && !allowConflict ){ |
| 1338 | fossil_fatal("abort due to unresolved merge conflicts; " |
| 1339 | "use --allow-conflict to override"); |
| 1340 | } |
| 1341 | |
| 1342 | /* Create the new manifest */ |
| 1343 | if( blob_size(&comment)==0 ){ |
| 1344 | blob_append(&comment, "(no comment)", -1); |
| 1345 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -886,13 +886,17 @@ | |
| 886 | |
| 887 | /* |
| 888 | ** Issue a warning and give the user an opportunity to abandon out |
| 889 | ** if a Unicode (UTF-16) byte-order-mark (BOM) or a \r\n line ending |
| 890 | ** is seen in a text file. |
| 891 | ** |
| 892 | ** Return 1 if the user pressed 'c'. In that case, the file will have |
| 893 | ** been converted to UTF-8 (if it was UTF-16) with NL line-endings, |
| 894 | ** and the original file will have been renamed to "<filename>-original". |
| 895 | */ |
| 896 | static int commit_warning( |
| 897 | Blob *p, /* The content of the file being committed. */ |
| 898 | int crnlOk, /* Non-zero if CR/NL warnings should be disabled. */ |
| 899 | int binOk, /* Non-zero if binary warnings should be disabled. */ |
| 900 | int unicodeOk, /* Non-zero if unicode warnings should be disabled. */ |
| 901 | const char *zFilename /* The full name of the file being committed. */ |
| 902 | ){ |
| @@ -900,56 +904,78 @@ | |
| 904 | int fUnicode; /* return value of starts_with_utf16_bom() */ |
| 905 | char *zMsg; /* Warning message */ |
| 906 | Blob fname; /* Relative pathname of the file */ |
| 907 | static int allOk = 0; /* Set to true to disable this routine */ |
| 908 | |
| 909 | if( allOk ) return 0; |
| 910 | fUnicode = starts_with_utf16_bom(p, 0); |
| 911 | eType = fUnicode ? looks_like_utf16(p) : looks_like_utf8(p); |
| 912 | if( eType==0 || eType==-1 || fUnicode ){ |
| 913 | const char *zWarning; |
| 914 | const char *zConvert = "c=convert/"; |
| 915 | Blob ans; |
| 916 | char cReply; |
| 917 | |
| 918 | if( eType==-1 && fUnicode ){ |
| 919 | if ( crnlOk && unicodeOk ){ |
| 920 | return 0; /* We don't want Unicode/CR/NL warnings for this file. */ |
| 921 | } |
| 922 | zWarning = "Unicode and CR/NL line endings"; |
| 923 | }else if( eType==-1 ){ |
| 924 | if( crnlOk ){ |
| 925 | return 0; /* We don't want CR/NL warnings for this file. */ |
| 926 | } |
| 927 | zWarning = "CR/NL line endings"; |
| 928 | }else if( eType==0 ){ |
| 929 | if( binOk ){ |
| 930 | return 0; /* We don't want binary warnings for this file. */ |
| 931 | } |
| 932 | zWarning = "binary data"; |
| 933 | zConvert = ""; /* We cannot convert binary files. */ |
| 934 | }else{ |
| 935 | if ( unicodeOk ){ |
| 936 | return 0; /* We don't want unicode warnings for this file. */ |
| 937 | } |
| 938 | zWarning = "Unicode"; |
| 939 | #ifndef _WIN32 |
| 940 | zConvert = ""; /* On Unix, we cannot easily convert Unicode files. */ |
| 941 | #endif |
| 942 | } |
| 943 | file_relative_name(zFilename, &fname, 0); |
| 944 | blob_zero(&ans); |
| 945 | zMsg = mprintf( |
| 946 | "%s contains %s. commit anyhow (a=all/%sy/N)? ", |
| 947 | blob_str(&fname), zWarning, zConvert); |
| 948 | prompt_user(zMsg, &ans); |
| 949 | fossil_free(zMsg); |
| 950 | cReply = blob_str(&ans)[0]; |
| 951 | if( cReply=='a' || cReply=='A' ){ |
| 952 | allOk = 1; |
| 953 | }else if( *zConvert && (cReply=='c' || cReply=='C') ){ |
| 954 | char *zOrig = file_newname(zFilename, "original", 1); |
| 955 | FILE *f; |
| 956 | blob_write_to_file(p, zOrig); |
| 957 | fossil_free(zOrig); |
| 958 | f = fossil_fopen(zFilename, "wb"); |
| 959 | if( fUnicode ) { |
| 960 | int bomSize; |
| 961 | const unsigned char *bom = get_utf8_bom(&bomSize); |
| 962 | fwrite(bom, 1, bomSize, f); |
| 963 | blob_to_utf8_no_bom(p, 0); |
| 964 | } |
| 965 | blob_remove_cr(p); |
| 966 | fwrite(blob_buffer(p), 1, blob_size(p), f); |
| 967 | fclose(f); |
| 968 | return 1; |
| 969 | }else if( cReply!='y' && cReply!='Y' ){ |
| 970 | fossil_fatal("Abandoning commit due to %s in %s", |
| 971 | zWarning, blob_str(&fname)); |
| 972 | } |
| 973 | blob_reset(&ans); |
| 974 | blob_reset(&fname); |
| 975 | } |
| 976 | return 0; |
| 977 | } |
| 978 | |
| 979 | /* |
| 980 | ** qsort() comparison routine for an array of pointers to strings. |
| 981 | */ |
| @@ -1065,10 +1091,11 @@ | |
| 1091 | Blob cksum1, cksum2; /* Before and after commit checksums */ |
| 1092 | Blob cksum1b; /* Checksum recorded in the manifest */ |
| 1093 | int szD; /* Size of the delta manifest */ |
| 1094 | int szB; /* Size of the baseline manifest */ |
| 1095 | int nConflict = 0; /* Number of unresolved merge conflicts */ |
| 1096 | int abortCommit = 0; |
| 1097 | Blob ans; |
| 1098 | char cReply; |
| 1099 | |
| 1100 | url_proxy_options(); |
| 1101 | noSign = find_option("nosign",0,0)!=0; |
| @@ -1312,11 +1339,11 @@ | |
| 1339 | }else{ |
| 1340 | blob_read_from_file(&content, zFullname); |
| 1341 | } |
| 1342 | /* Do not emit any warnings when they are disabled. */ |
| 1343 | if( !noWarningFlag ){ |
| 1344 | abortCommit |= commit_warning(&content, crnlOk, binOk, unicodeOk, zFullname); |
| 1345 | } |
| 1346 | if( chnged==1 && contains_merge_marker(&content) ){ |
| 1347 | Blob fname; /* Relative pathname of the file */ |
| 1348 | |
| 1349 | nConflict++; |
| @@ -1335,10 +1362,12 @@ | |
| 1362 | } |
| 1363 | db_finalize(&q); |
| 1364 | if( nConflict && !allowConflict ){ |
| 1365 | fossil_fatal("abort due to unresolved merge conflicts; " |
| 1366 | "use --allow-conflict to override"); |
| 1367 | } else if( abortCommit ){ |
| 1368 | fossil_fatal("files are converted on your request. Please re-test before committing"); |
| 1369 | } |
| 1370 | |
| 1371 | /* Create the new manifest */ |
| 1372 | if( blob_size(&comment)==0 ){ |
| 1373 | blob_append(&comment, "(no comment)", -1); |
| 1374 |