Fossil SCM
a little consistancy: Allow lower and uppercase for all commit responds, so if Caps-Lock hangs that doesn't matter any more.
Commit
d503cfd430a20cee537fcc7d649a5cddd1244593
Parent
63565631d7030c8…
1 file changed
+44
-40
+44
-40
| --- src/checkin.c | ||
| +++ src/checkin.c | ||
| @@ -33,17 +33,17 @@ | ||
| 33 | 33 | */ |
| 34 | 34 | static void status_report( |
| 35 | 35 | Blob *report, /* Append the status report here */ |
| 36 | 36 | const char *zPrefix, /* Prefix on each line of the report */ |
| 37 | 37 | int missingIsFatal, /* MISSING and NOT_A_FILE are fatal errors */ |
| 38 | - int cwdRelative /* Report relative to the current working dir */ | |
| 38 | + int cwdRelative /* Report relative to the current working dir */ | |
| 39 | 39 | ){ |
| 40 | 40 | Stmt q; |
| 41 | 41 | int nPrefix = strlen(zPrefix); |
| 42 | 42 | int nErr = 0; |
| 43 | 43 | Blob rewrittenPathname; |
| 44 | - db_prepare(&q, | |
| 44 | + db_prepare(&q, | |
| 45 | 45 | "SELECT pathname, deleted, chnged, rid, coalesce(origname!=pathname,0)" |
| 46 | 46 | " FROM vfile " |
| 47 | 47 | " WHERE is_selected(id)" |
| 48 | 48 | " AND (chnged OR deleted OR rid=0 OR pathname!=origname) ORDER BY 1" |
| 49 | 49 | ); |
| @@ -150,11 +150,11 @@ | ||
| 150 | 150 | ** directory. |
| 151 | 151 | ** --sha1sum Verify file status using SHA1 hashing rather |
| 152 | 152 | ** than relying on file mtimes. |
| 153 | 153 | ** --header Identify the repository if there are changes |
| 154 | 154 | ** -v Say "no changes" if there are none |
| 155 | -** | |
| 155 | +** | |
| 156 | 156 | ** See also: extra, ls, status |
| 157 | 157 | */ |
| 158 | 158 | void changes_cmd(void){ |
| 159 | 159 | Blob report; |
| 160 | 160 | int vid; |
| @@ -315,12 +315,12 @@ | ||
| 315 | 315 | ** Pathnames are displayed according to the "relative-paths" setting, |
| 316 | 316 | ** unless overridden by the --abs-paths or --rel-paths options. |
| 317 | 317 | ** |
| 318 | 318 | ** Options: |
| 319 | 319 | ** --abs-paths Display absolute pathnames. |
| 320 | -** --dotfiles include files beginning with a dot (".") | |
| 321 | -** --ignore <CSG> ignore files matching patterns from the | |
| 320 | +** --dotfiles include files beginning with a dot (".") | |
| 321 | +** --ignore <CSG> ignore files matching patterns from the | |
| 322 | 322 | ** --rel-paths Display pathnames relative to the current working |
| 323 | 323 | ** directory. |
| 324 | 324 | ** |
| 325 | 325 | ** See also: changes, clean, status |
| 326 | 326 | */ |
| @@ -347,11 +347,11 @@ | ||
| 347 | 347 | zIgnoreFlag = db_get("ignore-glob", 0); |
| 348 | 348 | } |
| 349 | 349 | pIgnore = glob_create(zIgnoreFlag); |
| 350 | 350 | vfile_scan(&path, blob_size(&path), scanFlags, pIgnore); |
| 351 | 351 | glob_free(pIgnore); |
| 352 | - db_prepare(&q, | |
| 352 | + db_prepare(&q, | |
| 353 | 353 | "SELECT x FROM sfile" |
| 354 | 354 | " WHERE x NOT IN (%s)" |
| 355 | 355 | " ORDER BY 1", |
| 356 | 356 | fossil_all_reserved_names() |
| 357 | 357 | ); |
| @@ -396,13 +396,13 @@ | ||
| 396 | 396 | ** The GLOBPATTERN is a comma-separated list of GLOB expressions for |
| 397 | 397 | ** files that are ignored. The GLOBPATTERN specified by the "ignore-glob" |
| 398 | 398 | ** is used if the --ignore option is omitted. |
| 399 | 399 | ** |
| 400 | 400 | ** Options: |
| 401 | -** --dotfiles include files beginning with a dot (".") | |
| 401 | +** --dotfiles include files beginning with a dot (".") | |
| 402 | 402 | ** --force Remove files without prompting |
| 403 | -** --ignore <CSG> ignore files matching patterns from the | |
| 403 | +** --ignore <CSG> ignore files matching patterns from the | |
| 404 | 404 | ** comma separated list of glob patterns. |
| 405 | 405 | ** --temp Remove only Fossil-generated temporary files |
| 406 | 406 | ** |
| 407 | 407 | ** See also: addremove, extra, status |
| 408 | 408 | */ |
| @@ -427,11 +427,11 @@ | ||
| 427 | 427 | n = strlen(g.zLocalRoot); |
| 428 | 428 | blob_init(&path, g.zLocalRoot, n-1); |
| 429 | 429 | pIgnore = glob_create(zIgnoreFlag); |
| 430 | 430 | vfile_scan(&path, blob_size(&path), scanFlags, pIgnore); |
| 431 | 431 | glob_free(pIgnore); |
| 432 | - db_prepare(&q, | |
| 432 | + db_prepare(&q, | |
| 433 | 433 | "SELECT %Q || x FROM sfile" |
| 434 | 434 | " WHERE x NOT IN (%s)" |
| 435 | 435 | " ORDER BY 1", |
| 436 | 436 | g.zLocalRoot, fossil_all_reserved_names() |
| 437 | 437 | ); |
| @@ -441,15 +441,17 @@ | ||
| 441 | 441 | while( db_step(&q)==SQLITE_ROW ){ |
| 442 | 442 | if( allFlag ){ |
| 443 | 443 | file_delete(db_column_text(&q, 0)); |
| 444 | 444 | }else{ |
| 445 | 445 | Blob ans; |
| 446 | + char cReply; | |
| 446 | 447 | char *prompt = mprintf("remove unmanaged file \"%s\" (y/N)? ", |
| 447 | 448 | db_column_text(&q, 0)); |
| 448 | 449 | blob_zero(&ans); |
| 449 | 450 | prompt_user(prompt, &ans); |
| 450 | - if( blob_str(&ans)[0]=='y' ){ | |
| 451 | + cReply = blob_str(&ans)[0]; | |
| 452 | + if( cReply=='y' || cReply=='Y' ){ | |
| 451 | 453 | file_delete(db_column_text(&q, 0)); |
| 452 | 454 | } |
| 453 | 455 | } |
| 454 | 456 | } |
| 455 | 457 | db_finalize(&q); |
| @@ -660,11 +662,11 @@ | ||
| 660 | 662 | #endif |
| 661 | 663 | } |
| 662 | 664 | |
| 663 | 665 | /* |
| 664 | 666 | ** zDate should be a valid date string. Convert this string into the |
| 665 | -** format YYYY-MM-DDTHH:MM:SS. If the string is not a valid date, | |
| 667 | +** format YYYY-MM-DDTHH:MM:SS. If the string is not a valid date, | |
| 666 | 668 | ** print a fatal error and quit. |
| 667 | 669 | */ |
| 668 | 670 | char *date_in_standard_format(const char *zInputDate){ |
| 669 | 671 | char *zDate; |
| 670 | 672 | if( g.perm.Setup && fossil_strcmp(zInputDate,"now")==0 ){ |
| @@ -871,11 +873,11 @@ | ||
| 871 | 873 | while( db_step(&q)==SQLITE_ROW ){ |
| 872 | 874 | const char *zBrTag = db_column_text(&q, 0); |
| 873 | 875 | blob_appendf(pOut, "T -%F *\n", zBrTag); |
| 874 | 876 | } |
| 875 | 877 | db_finalize(&q); |
| 876 | - } | |
| 878 | + } | |
| 877 | 879 | blob_appendf(pOut, "U %F\n", zUserOvrd ? zUserOvrd : g.zLogin); |
| 878 | 880 | md5sum_blob(pOut, &mcksum); |
| 879 | 881 | blob_appendf(pOut, "Z %b\n", &mcksum); |
| 880 | 882 | if( pnFBcard ) *pnFBcard = nFBcard; |
| 881 | 883 | } |
| @@ -890,11 +892,10 @@ | ||
| 890 | 892 | int n; /* Size of the file in bytes */ |
| 891 | 893 | int lastNl = 0; /* Characters since last \n */ |
| 892 | 894 | int i; /* Loop counter */ |
| 893 | 895 | char *zMsg; /* Warning message */ |
| 894 | 896 | Blob fname; /* Relative pathname of the file */ |
| 895 | - Blob ans; /* Answer to continue prompt */ | |
| 896 | 897 | static int allOk = 0; /* Set to true to disable this routine */ |
| 897 | 898 | |
| 898 | 899 | if( allOk ) return; |
| 899 | 900 | z = (unsigned char*)blob_buffer(p); |
| 900 | 901 | n = blob_size(p); |
| @@ -912,23 +913,25 @@ | ||
| 912 | 913 | /* Binary if any line longer than 8191, see looks_like_binary() */ |
| 913 | 914 | if( lastNl>8191 ) return; |
| 914 | 915 | } |
| 915 | 916 | } |
| 916 | 917 | if( nCrNl ){ |
| 917 | - char c; | |
| 918 | + Blob ans; | |
| 919 | + char cReply; | |
| 920 | + | |
| 918 | 921 | file_relative_name(zFilename, &fname, 0); |
| 919 | 922 | blob_zero(&ans); |
| 920 | 923 | zMsg = mprintf( |
| 921 | - "%s contains CR/NL line endings; commit anyhow (yes/no/all)?", | |
| 924 | + "%s contains CR/NL line endings; commit anyhow (yes/no/all)?", | |
| 922 | 925 | blob_str(&fname)); |
| 923 | 926 | prompt_user(zMsg, &ans); |
| 924 | 927 | fossil_free(zMsg); |
| 925 | - c = blob_str(&ans)[0]; | |
| 926 | - if( c=='a' ){ | |
| 928 | + cReply = blob_str(&ans)[0]; | |
| 929 | + if( cReply=='a' || cReply=='A' ){ | |
| 927 | 930 | allOk = 1; |
| 928 | - }else if( c!='y' ){ | |
| 929 | - fossil_fatal("Abandoning commit due to CR+NL line endings in %s", | |
| 931 | + }else if( cReply=='y' || cReply=='Y' ){ | |
| 932 | + fossil_fatal("Abandoning commit due to CR/NL line endings in %s", | |
| 930 | 933 | blob_str(&fname)); |
| 931 | 934 | } |
| 932 | 935 | blob_reset(&ans); |
| 933 | 936 | blob_reset(&fname); |
| 934 | 937 | } |
| @@ -949,11 +952,11 @@ | ||
| 949 | 952 | ** |
| 950 | 953 | ** Usage: %fossil commit ?OPTIONS? ?FILE...? |
| 951 | 954 | ** |
| 952 | 955 | ** Create a new version containing all of the changes in the current |
| 953 | 956 | ** checkout. You will be prompted to enter a check-in comment unless |
| 954 | -** the comment has been specified on the command-line using "-m" or a | |
| 957 | +** the comment has been specified on the command-line using "-m" or a | |
| 955 | 958 | ** file containing the comment using -M. The editor defined in the |
| 956 | 959 | ** "editor" fossil option (see %fossil help set) will be used, or from |
| 957 | 960 | ** the "VISUAL" or "EDITOR" environment variables (in that order) if |
| 958 | 961 | ** no editor is set. |
| 959 | 962 | ** |
| @@ -993,11 +996,11 @@ | ||
| 993 | 996 | ** --message-file|-M FILE read the commit comment from given file |
| 994 | 997 | ** --nosign do not attempt to sign this commit with gpg |
| 995 | 998 | ** --private do not sync changes and their descendants |
| 996 | 999 | ** --tag TAG-NAME assign given tag TAG-NAME to the checkin |
| 997 | 1000 | ** --conflict allow unresolved merge conflicts |
| 998 | -** | |
| 1001 | +** | |
| 999 | 1002 | ** See also: branch, changes, checkout, extra, sync |
| 1000 | 1003 | */ |
| 1001 | 1004 | void commit_cmd(void){ |
| 1002 | 1005 | int hasChanges; /* True if unsaved changes exist */ |
| 1003 | 1006 | int vid; /* blob-id of parent version */ |
| @@ -1031,11 +1034,13 @@ | ||
| 1031 | 1034 | Blob cksum1, cksum2; /* Before and after commit checksums */ |
| 1032 | 1035 | Blob cksum1b; /* Checksum recorded in the manifest */ |
| 1033 | 1036 | int szD; /* Size of the delta manifest */ |
| 1034 | 1037 | int szB; /* Size of the baseline manifest */ |
| 1035 | 1038 | int nConflict = 0; /* Number of unresolved merge conflicts */ |
| 1036 | - | |
| 1039 | + Blob ans; | |
| 1040 | + char cReply; | |
| 1041 | + | |
| 1037 | 1042 | url_proxy_options(); |
| 1038 | 1043 | noSign = find_option("nosign",0,0)!=0; |
| 1039 | 1044 | forceDelta = find_option("delta",0,0)!=0; |
| 1040 | 1045 | forceBaseline = find_option("baseline",0,0)!=0; |
| 1041 | 1046 | if( forceDelta && forceBaseline ){ |
| @@ -1095,11 +1100,10 @@ | ||
| 1095 | 1100 | /* |
| 1096 | 1101 | ** Autosync if autosync is enabled and this is not a private check-in. |
| 1097 | 1102 | */ |
| 1098 | 1103 | if( !g.markPrivate ){ |
| 1099 | 1104 | if( autosync(AUTOSYNC_PULL) ){ |
| 1100 | - Blob ans; | |
| 1101 | 1105 | blob_zero(&ans); |
| 1102 | 1106 | prompt_user("continue in spite of sync failure (y/N)? ", &ans); |
| 1103 | 1107 | if( blob_str(&ans)[0]!='y' ){ |
| 1104 | 1108 | fossil_exit(1); |
| 1105 | 1109 | } |
| @@ -1108,14 +1112,14 @@ | ||
| 1108 | 1112 | |
| 1109 | 1113 | /* Require confirmation to continue with the check-in if there is |
| 1110 | 1114 | ** clock skew |
| 1111 | 1115 | */ |
| 1112 | 1116 | if( g.clockSkewSeen ){ |
| 1113 | - Blob ans; | |
| 1114 | 1117 | blob_zero(&ans); |
| 1115 | 1118 | prompt_user("continue in spite of time skew (y/N)? ", &ans); |
| 1116 | - if( blob_str(&ans)[0]!='y' ){ | |
| 1119 | + cReply = blob_str(&ans)[0]; | |
| 1120 | + if( cReply!='y' && cReply!='Y' ){ | |
| 1117 | 1121 | fossil_exit(1); |
| 1118 | 1122 | } |
| 1119 | 1123 | } |
| 1120 | 1124 | |
| 1121 | 1125 | /* There are two ways this command may be executed. If there are |
| @@ -1139,11 +1143,11 @@ | ||
| 1139 | 1143 | ** Check that the user exists. |
| 1140 | 1144 | */ |
| 1141 | 1145 | if( !db_exists("SELECT 1 FROM user WHERE login=%Q", g.zLogin) ){ |
| 1142 | 1146 | fossil_fatal("no such user: %s", g.zLogin); |
| 1143 | 1147 | } |
| 1144 | - | |
| 1148 | + | |
| 1145 | 1149 | hasChanges = unsaved_changes(); |
| 1146 | 1150 | db_begin_transaction(); |
| 1147 | 1151 | db_record_repository_filename(0); |
| 1148 | 1152 | if( hasChanges==0 && !isAMerge && !forceFlag ){ |
| 1149 | 1153 | fossil_fatal("nothing has changed"); |
| @@ -1170,11 +1174,11 @@ | ||
| 1170 | 1174 | if( zBranch==0 && forceFlag==0 && g.markPrivate==0 && !is_a_leaf(vid) ){ |
| 1171 | 1175 | fossil_fatal("would fork. \"update\" first or use -f or --force."); |
| 1172 | 1176 | } |
| 1173 | 1177 | |
| 1174 | 1178 | /* |
| 1175 | - ** Do not allow a commit against a closed leaf | |
| 1179 | + ** Do not allow a commit against a closed leaf | |
| 1176 | 1180 | */ |
| 1177 | 1181 | if( db_exists("SELECT 1 FROM tagxref" |
| 1178 | 1182 | " WHERE tagid=%d AND rid=%d AND tagtype>0", |
| 1179 | 1183 | TAG_CLOSED, vid) ){ |
| 1180 | 1184 | fossil_fatal("cannot commit against a closed leaf"); |
| @@ -1190,31 +1194,31 @@ | ||
| 1190 | 1194 | blob_strip_bom(&comment, 1); |
| 1191 | 1195 | }else{ |
| 1192 | 1196 | char *zInit = db_text(0, "SELECT value FROM vvar WHERE name='ci-comment'"); |
| 1193 | 1197 | prepare_commit_comment(&comment, zInit, zBranch, vid, zUserOvrd); |
| 1194 | 1198 | if( zInit && zInit[0] && fossil_strcmp(zInit, blob_str(&comment))==0 ){ |
| 1195 | - Blob ans; | |
| 1196 | 1199 | blob_zero(&ans); |
| 1197 | 1200 | prompt_user("unchanged check-in comment. continue (y/N)? ", &ans); |
| 1198 | - if( blob_str(&ans)[0]!='y' ) fossil_exit(1);; | |
| 1201 | + cReply = blob_str(&ans)[0]; | |
| 1202 | + if( cReply!='y' && cReply!='Y' ) fossil_exit(1);; | |
| 1199 | 1203 | } |
| 1200 | 1204 | free(zInit); |
| 1201 | 1205 | } |
| 1202 | 1206 | if( blob_size(&comment)==0 ){ |
| 1203 | - Blob ans; | |
| 1204 | 1207 | blob_zero(&ans); |
| 1205 | 1208 | prompt_user("empty check-in comment. continue (y/N)? ", &ans); |
| 1206 | - if( blob_str(&ans)[0]!='y' ){ | |
| 1209 | + cReply = blob_str(&ans)[0]; | |
| 1210 | + if( cReply!='y' && cReply!='Y' ){ | |
| 1207 | 1211 | fossil_exit(1); |
| 1208 | 1212 | } |
| 1209 | 1213 | }else{ |
| 1210 | 1214 | db_multi_exec("REPLACE INTO vvar VALUES('ci-comment',%B)", &comment); |
| 1211 | 1215 | db_end_transaction(0); |
| 1212 | 1216 | db_begin_transaction(); |
| 1213 | 1217 | } |
| 1214 | 1218 | |
| 1215 | - /* Step 1: Insert records for all modified files into the blob | |
| 1219 | + /* Step 1: Insert records for all modified files into the blob | |
| 1216 | 1220 | ** table. If there were arguments passed to this command, only |
| 1217 | 1221 | ** the identified fils are inserted (if they have been modified). |
| 1218 | 1222 | */ |
| 1219 | 1223 | db_prepare(&q, |
| 1220 | 1224 | "SELECT id, %Q || pathname, mrid, %s, chnged FROM vfile " |
| @@ -1236,11 +1240,11 @@ | ||
| 1236 | 1240 | blob_zero(&content); |
| 1237 | 1241 | if( file_wd_islink(zFullname) ){ |
| 1238 | 1242 | /* Instead of file content, put link destination path */ |
| 1239 | 1243 | blob_read_link(&content, zFullname); |
| 1240 | 1244 | }else{ |
| 1241 | - blob_read_from_file(&content, zFullname); | |
| 1245 | + blob_read_from_file(&content, zFullname); | |
| 1242 | 1246 | } |
| 1243 | 1247 | if( !crnlOk ) cr_warning(&content, zFullname); |
| 1244 | 1248 | if( chnged==1 && contains_merge_marker(&content) ){ |
| 1245 | 1249 | nConflict++; |
| 1246 | 1250 | fossil_print("possible unresolved merge conflict in %s\n", |
| @@ -1319,20 +1323,20 @@ | ||
| 1319 | 1323 | }else if( forceDelta ){ |
| 1320 | 1324 | fossil_panic("unable to find a baseline-manifest for the delta"); |
| 1321 | 1325 | } |
| 1322 | 1326 | } |
| 1323 | 1327 | if( !noSign && !g.markPrivate && clearsign(&manifest, &manifest) ){ |
| 1324 | - Blob ans; | |
| 1325 | 1328 | blob_zero(&ans); |
| 1326 | 1329 | prompt_user("unable to sign manifest. continue (y/N)? ", &ans); |
| 1327 | - if( blob_str(&ans)[0]!='y' ){ | |
| 1330 | + cReply = blob_str(&ans)[0]; | |
| 1331 | + if( cReply!='y' && cReply!='Y' ){ | |
| 1328 | 1332 | fossil_exit(1); |
| 1329 | 1333 | } |
| 1330 | 1334 | } |
| 1331 | 1335 | |
| 1332 | 1336 | /* If the --test option is specified, output the manifest file |
| 1333 | - ** and rollback the transaction. | |
| 1337 | + ** and rollback the transaction. | |
| 1334 | 1338 | */ |
| 1335 | 1339 | if( testRun ){ |
| 1336 | 1340 | blob_write_to_file(&manifest, ""); |
| 1337 | 1341 | } |
| 1338 | 1342 | |
| @@ -1360,11 +1364,11 @@ | ||
| 1360 | 1364 | blob_write_to_file(&muuid, zManifestFile); |
| 1361 | 1365 | free(zManifestFile); |
| 1362 | 1366 | blob_reset(&muuid); |
| 1363 | 1367 | } |
| 1364 | 1368 | |
| 1365 | - | |
| 1369 | + | |
| 1366 | 1370 | /* Update the vfile and vmerge tables */ |
| 1367 | 1371 | db_multi_exec( |
| 1368 | 1372 | "DELETE FROM vfile WHERE (vid!=%d OR deleted) AND is_selected(id);" |
| 1369 | 1373 | "DELETE FROM vmerge;" |
| 1370 | 1374 | "UPDATE vfile SET vid=%d;" |
| @@ -1384,11 +1388,11 @@ | ||
| 1384 | 1388 | vfile_compare_repository_to_disk(nvid); |
| 1385 | 1389 | fossil_fatal("working checkout does not match what would have ended " |
| 1386 | 1390 | "up in the repository: %b versus %b", |
| 1387 | 1391 | &cksum1, &cksum2); |
| 1388 | 1392 | } |
| 1389 | - | |
| 1393 | + | |
| 1390 | 1394 | /* Verify that the manifest checksum matches the expected checksum */ |
| 1391 | 1395 | vfile_aggregate_checksum_manifest(nvid, &cksum2, &cksum1b); |
| 1392 | 1396 | if( blob_compare(&cksum1, &cksum1b) ){ |
| 1393 | 1397 | fossil_fatal("manifest checksum self-test failed: " |
| 1394 | 1398 | "%b versus %b", &cksum1, &cksum1b); |
| @@ -1396,11 +1400,11 @@ | ||
| 1396 | 1400 | if( blob_compare(&cksum1, &cksum2) ){ |
| 1397 | 1401 | fossil_fatal( |
| 1398 | 1402 | "working checkout does not match manifest after commit: " |
| 1399 | 1403 | "%b versus %b", &cksum1, &cksum2); |
| 1400 | 1404 | } |
| 1401 | - | |
| 1405 | + | |
| 1402 | 1406 | /* Verify that the commit did not modify any disk images. */ |
| 1403 | 1407 | vfile_aggregate_checksum_disk(nvid, &cksum2); |
| 1404 | 1408 | if( blob_compare(&cksum1, &cksum2) ){ |
| 1405 | 1409 | fossil_fatal("working checkout before and after commit does not match"); |
| 1406 | 1410 | } |
| @@ -1416,11 +1420,11 @@ | ||
| 1416 | 1420 | exit(1); |
| 1417 | 1421 | } |
| 1418 | 1422 | db_end_transaction(0); |
| 1419 | 1423 | |
| 1420 | 1424 | if( !g.markPrivate ){ |
| 1421 | - autosync(AUTOSYNC_PUSH); | |
| 1425 | + autosync(AUTOSYNC_PUSH); | |
| 1422 | 1426 | } |
| 1423 | 1427 | if( count_nonbranch_children(vid)>1 ){ |
| 1424 | 1428 | fossil_print("**** warning: a fork has occurred *****\n"); |
| 1425 | 1429 | } |
| 1426 | 1430 | } |
| 1427 | 1431 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -33,17 +33,17 @@ | |
| 33 | */ |
| 34 | static void status_report( |
| 35 | Blob *report, /* Append the status report here */ |
| 36 | const char *zPrefix, /* Prefix on each line of the report */ |
| 37 | int missingIsFatal, /* MISSING and NOT_A_FILE are fatal errors */ |
| 38 | int cwdRelative /* Report relative to the current working dir */ |
| 39 | ){ |
| 40 | Stmt q; |
| 41 | int nPrefix = strlen(zPrefix); |
| 42 | int nErr = 0; |
| 43 | Blob rewrittenPathname; |
| 44 | db_prepare(&q, |
| 45 | "SELECT pathname, deleted, chnged, rid, coalesce(origname!=pathname,0)" |
| 46 | " FROM vfile " |
| 47 | " WHERE is_selected(id)" |
| 48 | " AND (chnged OR deleted OR rid=0 OR pathname!=origname) ORDER BY 1" |
| 49 | ); |
| @@ -150,11 +150,11 @@ | |
| 150 | ** directory. |
| 151 | ** --sha1sum Verify file status using SHA1 hashing rather |
| 152 | ** than relying on file mtimes. |
| 153 | ** --header Identify the repository if there are changes |
| 154 | ** -v Say "no changes" if there are none |
| 155 | ** |
| 156 | ** See also: extra, ls, status |
| 157 | */ |
| 158 | void changes_cmd(void){ |
| 159 | Blob report; |
| 160 | int vid; |
| @@ -315,12 +315,12 @@ | |
| 315 | ** Pathnames are displayed according to the "relative-paths" setting, |
| 316 | ** unless overridden by the --abs-paths or --rel-paths options. |
| 317 | ** |
| 318 | ** Options: |
| 319 | ** --abs-paths Display absolute pathnames. |
| 320 | ** --dotfiles include files beginning with a dot (".") |
| 321 | ** --ignore <CSG> ignore files matching patterns from the |
| 322 | ** --rel-paths Display pathnames relative to the current working |
| 323 | ** directory. |
| 324 | ** |
| 325 | ** See also: changes, clean, status |
| 326 | */ |
| @@ -347,11 +347,11 @@ | |
| 347 | zIgnoreFlag = db_get("ignore-glob", 0); |
| 348 | } |
| 349 | pIgnore = glob_create(zIgnoreFlag); |
| 350 | vfile_scan(&path, blob_size(&path), scanFlags, pIgnore); |
| 351 | glob_free(pIgnore); |
| 352 | db_prepare(&q, |
| 353 | "SELECT x FROM sfile" |
| 354 | " WHERE x NOT IN (%s)" |
| 355 | " ORDER BY 1", |
| 356 | fossil_all_reserved_names() |
| 357 | ); |
| @@ -396,13 +396,13 @@ | |
| 396 | ** The GLOBPATTERN is a comma-separated list of GLOB expressions for |
| 397 | ** files that are ignored. The GLOBPATTERN specified by the "ignore-glob" |
| 398 | ** is used if the --ignore option is omitted. |
| 399 | ** |
| 400 | ** Options: |
| 401 | ** --dotfiles include files beginning with a dot (".") |
| 402 | ** --force Remove files without prompting |
| 403 | ** --ignore <CSG> ignore files matching patterns from the |
| 404 | ** comma separated list of glob patterns. |
| 405 | ** --temp Remove only Fossil-generated temporary files |
| 406 | ** |
| 407 | ** See also: addremove, extra, status |
| 408 | */ |
| @@ -427,11 +427,11 @@ | |
| 427 | n = strlen(g.zLocalRoot); |
| 428 | blob_init(&path, g.zLocalRoot, n-1); |
| 429 | pIgnore = glob_create(zIgnoreFlag); |
| 430 | vfile_scan(&path, blob_size(&path), scanFlags, pIgnore); |
| 431 | glob_free(pIgnore); |
| 432 | db_prepare(&q, |
| 433 | "SELECT %Q || x FROM sfile" |
| 434 | " WHERE x NOT IN (%s)" |
| 435 | " ORDER BY 1", |
| 436 | g.zLocalRoot, fossil_all_reserved_names() |
| 437 | ); |
| @@ -441,15 +441,17 @@ | |
| 441 | while( db_step(&q)==SQLITE_ROW ){ |
| 442 | if( allFlag ){ |
| 443 | file_delete(db_column_text(&q, 0)); |
| 444 | }else{ |
| 445 | Blob ans; |
| 446 | char *prompt = mprintf("remove unmanaged file \"%s\" (y/N)? ", |
| 447 | db_column_text(&q, 0)); |
| 448 | blob_zero(&ans); |
| 449 | prompt_user(prompt, &ans); |
| 450 | if( blob_str(&ans)[0]=='y' ){ |
| 451 | file_delete(db_column_text(&q, 0)); |
| 452 | } |
| 453 | } |
| 454 | } |
| 455 | db_finalize(&q); |
| @@ -660,11 +662,11 @@ | |
| 660 | #endif |
| 661 | } |
| 662 | |
| 663 | /* |
| 664 | ** zDate should be a valid date string. Convert this string into the |
| 665 | ** format YYYY-MM-DDTHH:MM:SS. If the string is not a valid date, |
| 666 | ** print a fatal error and quit. |
| 667 | */ |
| 668 | char *date_in_standard_format(const char *zInputDate){ |
| 669 | char *zDate; |
| 670 | if( g.perm.Setup && fossil_strcmp(zInputDate,"now")==0 ){ |
| @@ -871,11 +873,11 @@ | |
| 871 | while( db_step(&q)==SQLITE_ROW ){ |
| 872 | const char *zBrTag = db_column_text(&q, 0); |
| 873 | blob_appendf(pOut, "T -%F *\n", zBrTag); |
| 874 | } |
| 875 | db_finalize(&q); |
| 876 | } |
| 877 | blob_appendf(pOut, "U %F\n", zUserOvrd ? zUserOvrd : g.zLogin); |
| 878 | md5sum_blob(pOut, &mcksum); |
| 879 | blob_appendf(pOut, "Z %b\n", &mcksum); |
| 880 | if( pnFBcard ) *pnFBcard = nFBcard; |
| 881 | } |
| @@ -890,11 +892,10 @@ | |
| 890 | int n; /* Size of the file in bytes */ |
| 891 | int lastNl = 0; /* Characters since last \n */ |
| 892 | int i; /* Loop counter */ |
| 893 | char *zMsg; /* Warning message */ |
| 894 | Blob fname; /* Relative pathname of the file */ |
| 895 | Blob ans; /* Answer to continue prompt */ |
| 896 | static int allOk = 0; /* Set to true to disable this routine */ |
| 897 | |
| 898 | if( allOk ) return; |
| 899 | z = (unsigned char*)blob_buffer(p); |
| 900 | n = blob_size(p); |
| @@ -912,23 +913,25 @@ | |
| 912 | /* Binary if any line longer than 8191, see looks_like_binary() */ |
| 913 | if( lastNl>8191 ) return; |
| 914 | } |
| 915 | } |
| 916 | if( nCrNl ){ |
| 917 | char c; |
| 918 | file_relative_name(zFilename, &fname, 0); |
| 919 | blob_zero(&ans); |
| 920 | zMsg = mprintf( |
| 921 | "%s contains CR/NL line endings; commit anyhow (yes/no/all)?", |
| 922 | blob_str(&fname)); |
| 923 | prompt_user(zMsg, &ans); |
| 924 | fossil_free(zMsg); |
| 925 | c = blob_str(&ans)[0]; |
| 926 | if( c=='a' ){ |
| 927 | allOk = 1; |
| 928 | }else if( c!='y' ){ |
| 929 | fossil_fatal("Abandoning commit due to CR+NL line endings in %s", |
| 930 | blob_str(&fname)); |
| 931 | } |
| 932 | blob_reset(&ans); |
| 933 | blob_reset(&fname); |
| 934 | } |
| @@ -949,11 +952,11 @@ | |
| 949 | ** |
| 950 | ** Usage: %fossil commit ?OPTIONS? ?FILE...? |
| 951 | ** |
| 952 | ** Create a new version containing all of the changes in the current |
| 953 | ** checkout. You will be prompted to enter a check-in comment unless |
| 954 | ** the comment has been specified on the command-line using "-m" or a |
| 955 | ** file containing the comment using -M. The editor defined in the |
| 956 | ** "editor" fossil option (see %fossil help set) will be used, or from |
| 957 | ** the "VISUAL" or "EDITOR" environment variables (in that order) if |
| 958 | ** no editor is set. |
| 959 | ** |
| @@ -993,11 +996,11 @@ | |
| 993 | ** --message-file|-M FILE read the commit comment from given file |
| 994 | ** --nosign do not attempt to sign this commit with gpg |
| 995 | ** --private do not sync changes and their descendants |
| 996 | ** --tag TAG-NAME assign given tag TAG-NAME to the checkin |
| 997 | ** --conflict allow unresolved merge conflicts |
| 998 | ** |
| 999 | ** See also: branch, changes, checkout, extra, sync |
| 1000 | */ |
| 1001 | void commit_cmd(void){ |
| 1002 | int hasChanges; /* True if unsaved changes exist */ |
| 1003 | int vid; /* blob-id of parent version */ |
| @@ -1031,11 +1034,13 @@ | |
| 1031 | Blob cksum1, cksum2; /* Before and after commit checksums */ |
| 1032 | Blob cksum1b; /* Checksum recorded in the manifest */ |
| 1033 | int szD; /* Size of the delta manifest */ |
| 1034 | int szB; /* Size of the baseline manifest */ |
| 1035 | int nConflict = 0; /* Number of unresolved merge conflicts */ |
| 1036 | |
| 1037 | url_proxy_options(); |
| 1038 | noSign = find_option("nosign",0,0)!=0; |
| 1039 | forceDelta = find_option("delta",0,0)!=0; |
| 1040 | forceBaseline = find_option("baseline",0,0)!=0; |
| 1041 | if( forceDelta && forceBaseline ){ |
| @@ -1095,11 +1100,10 @@ | |
| 1095 | /* |
| 1096 | ** Autosync if autosync is enabled and this is not a private check-in. |
| 1097 | */ |
| 1098 | if( !g.markPrivate ){ |
| 1099 | if( autosync(AUTOSYNC_PULL) ){ |
| 1100 | Blob ans; |
| 1101 | blob_zero(&ans); |
| 1102 | prompt_user("continue in spite of sync failure (y/N)? ", &ans); |
| 1103 | if( blob_str(&ans)[0]!='y' ){ |
| 1104 | fossil_exit(1); |
| 1105 | } |
| @@ -1108,14 +1112,14 @@ | |
| 1108 | |
| 1109 | /* Require confirmation to continue with the check-in if there is |
| 1110 | ** clock skew |
| 1111 | */ |
| 1112 | if( g.clockSkewSeen ){ |
| 1113 | Blob ans; |
| 1114 | blob_zero(&ans); |
| 1115 | prompt_user("continue in spite of time skew (y/N)? ", &ans); |
| 1116 | if( blob_str(&ans)[0]!='y' ){ |
| 1117 | fossil_exit(1); |
| 1118 | } |
| 1119 | } |
| 1120 | |
| 1121 | /* There are two ways this command may be executed. If there are |
| @@ -1139,11 +1143,11 @@ | |
| 1139 | ** Check that the user exists. |
| 1140 | */ |
| 1141 | if( !db_exists("SELECT 1 FROM user WHERE login=%Q", g.zLogin) ){ |
| 1142 | fossil_fatal("no such user: %s", g.zLogin); |
| 1143 | } |
| 1144 | |
| 1145 | hasChanges = unsaved_changes(); |
| 1146 | db_begin_transaction(); |
| 1147 | db_record_repository_filename(0); |
| 1148 | if( hasChanges==0 && !isAMerge && !forceFlag ){ |
| 1149 | fossil_fatal("nothing has changed"); |
| @@ -1170,11 +1174,11 @@ | |
| 1170 | if( zBranch==0 && forceFlag==0 && g.markPrivate==0 && !is_a_leaf(vid) ){ |
| 1171 | fossil_fatal("would fork. \"update\" first or use -f or --force."); |
| 1172 | } |
| 1173 | |
| 1174 | /* |
| 1175 | ** Do not allow a commit against a closed leaf |
| 1176 | */ |
| 1177 | if( db_exists("SELECT 1 FROM tagxref" |
| 1178 | " WHERE tagid=%d AND rid=%d AND tagtype>0", |
| 1179 | TAG_CLOSED, vid) ){ |
| 1180 | fossil_fatal("cannot commit against a closed leaf"); |
| @@ -1190,31 +1194,31 @@ | |
| 1190 | blob_strip_bom(&comment, 1); |
| 1191 | }else{ |
| 1192 | char *zInit = db_text(0, "SELECT value FROM vvar WHERE name='ci-comment'"); |
| 1193 | prepare_commit_comment(&comment, zInit, zBranch, vid, zUserOvrd); |
| 1194 | if( zInit && zInit[0] && fossil_strcmp(zInit, blob_str(&comment))==0 ){ |
| 1195 | Blob ans; |
| 1196 | blob_zero(&ans); |
| 1197 | prompt_user("unchanged check-in comment. continue (y/N)? ", &ans); |
| 1198 | if( blob_str(&ans)[0]!='y' ) fossil_exit(1);; |
| 1199 | } |
| 1200 | free(zInit); |
| 1201 | } |
| 1202 | if( blob_size(&comment)==0 ){ |
| 1203 | Blob ans; |
| 1204 | blob_zero(&ans); |
| 1205 | prompt_user("empty check-in comment. continue (y/N)? ", &ans); |
| 1206 | if( blob_str(&ans)[0]!='y' ){ |
| 1207 | fossil_exit(1); |
| 1208 | } |
| 1209 | }else{ |
| 1210 | db_multi_exec("REPLACE INTO vvar VALUES('ci-comment',%B)", &comment); |
| 1211 | db_end_transaction(0); |
| 1212 | db_begin_transaction(); |
| 1213 | } |
| 1214 | |
| 1215 | /* Step 1: Insert records for all modified files into the blob |
| 1216 | ** table. If there were arguments passed to this command, only |
| 1217 | ** the identified fils are inserted (if they have been modified). |
| 1218 | */ |
| 1219 | db_prepare(&q, |
| 1220 | "SELECT id, %Q || pathname, mrid, %s, chnged FROM vfile " |
| @@ -1236,11 +1240,11 @@ | |
| 1236 | blob_zero(&content); |
| 1237 | if( file_wd_islink(zFullname) ){ |
| 1238 | /* Instead of file content, put link destination path */ |
| 1239 | blob_read_link(&content, zFullname); |
| 1240 | }else{ |
| 1241 | blob_read_from_file(&content, zFullname); |
| 1242 | } |
| 1243 | if( !crnlOk ) cr_warning(&content, zFullname); |
| 1244 | if( chnged==1 && contains_merge_marker(&content) ){ |
| 1245 | nConflict++; |
| 1246 | fossil_print("possible unresolved merge conflict in %s\n", |
| @@ -1319,20 +1323,20 @@ | |
| 1319 | }else if( forceDelta ){ |
| 1320 | fossil_panic("unable to find a baseline-manifest for the delta"); |
| 1321 | } |
| 1322 | } |
| 1323 | if( !noSign && !g.markPrivate && clearsign(&manifest, &manifest) ){ |
| 1324 | Blob ans; |
| 1325 | blob_zero(&ans); |
| 1326 | prompt_user("unable to sign manifest. continue (y/N)? ", &ans); |
| 1327 | if( blob_str(&ans)[0]!='y' ){ |
| 1328 | fossil_exit(1); |
| 1329 | } |
| 1330 | } |
| 1331 | |
| 1332 | /* If the --test option is specified, output the manifest file |
| 1333 | ** and rollback the transaction. |
| 1334 | */ |
| 1335 | if( testRun ){ |
| 1336 | blob_write_to_file(&manifest, ""); |
| 1337 | } |
| 1338 | |
| @@ -1360,11 +1364,11 @@ | |
| 1360 | blob_write_to_file(&muuid, zManifestFile); |
| 1361 | free(zManifestFile); |
| 1362 | blob_reset(&muuid); |
| 1363 | } |
| 1364 | |
| 1365 | |
| 1366 | /* Update the vfile and vmerge tables */ |
| 1367 | db_multi_exec( |
| 1368 | "DELETE FROM vfile WHERE (vid!=%d OR deleted) AND is_selected(id);" |
| 1369 | "DELETE FROM vmerge;" |
| 1370 | "UPDATE vfile SET vid=%d;" |
| @@ -1384,11 +1388,11 @@ | |
| 1384 | vfile_compare_repository_to_disk(nvid); |
| 1385 | fossil_fatal("working checkout does not match what would have ended " |
| 1386 | "up in the repository: %b versus %b", |
| 1387 | &cksum1, &cksum2); |
| 1388 | } |
| 1389 | |
| 1390 | /* Verify that the manifest checksum matches the expected checksum */ |
| 1391 | vfile_aggregate_checksum_manifest(nvid, &cksum2, &cksum1b); |
| 1392 | if( blob_compare(&cksum1, &cksum1b) ){ |
| 1393 | fossil_fatal("manifest checksum self-test failed: " |
| 1394 | "%b versus %b", &cksum1, &cksum1b); |
| @@ -1396,11 +1400,11 @@ | |
| 1396 | if( blob_compare(&cksum1, &cksum2) ){ |
| 1397 | fossil_fatal( |
| 1398 | "working checkout does not match manifest after commit: " |
| 1399 | "%b versus %b", &cksum1, &cksum2); |
| 1400 | } |
| 1401 | |
| 1402 | /* Verify that the commit did not modify any disk images. */ |
| 1403 | vfile_aggregate_checksum_disk(nvid, &cksum2); |
| 1404 | if( blob_compare(&cksum1, &cksum2) ){ |
| 1405 | fossil_fatal("working checkout before and after commit does not match"); |
| 1406 | } |
| @@ -1416,11 +1420,11 @@ | |
| 1416 | exit(1); |
| 1417 | } |
| 1418 | db_end_transaction(0); |
| 1419 | |
| 1420 | if( !g.markPrivate ){ |
| 1421 | autosync(AUTOSYNC_PUSH); |
| 1422 | } |
| 1423 | if( count_nonbranch_children(vid)>1 ){ |
| 1424 | fossil_print("**** warning: a fork has occurred *****\n"); |
| 1425 | } |
| 1426 | } |
| 1427 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -33,17 +33,17 @@ | |
| 33 | */ |
| 34 | static void status_report( |
| 35 | Blob *report, /* Append the status report here */ |
| 36 | const char *zPrefix, /* Prefix on each line of the report */ |
| 37 | int missingIsFatal, /* MISSING and NOT_A_FILE are fatal errors */ |
| 38 | int cwdRelative /* Report relative to the current working dir */ |
| 39 | ){ |
| 40 | Stmt q; |
| 41 | int nPrefix = strlen(zPrefix); |
| 42 | int nErr = 0; |
| 43 | Blob rewrittenPathname; |
| 44 | db_prepare(&q, |
| 45 | "SELECT pathname, deleted, chnged, rid, coalesce(origname!=pathname,0)" |
| 46 | " FROM vfile " |
| 47 | " WHERE is_selected(id)" |
| 48 | " AND (chnged OR deleted OR rid=0 OR pathname!=origname) ORDER BY 1" |
| 49 | ); |
| @@ -150,11 +150,11 @@ | |
| 150 | ** directory. |
| 151 | ** --sha1sum Verify file status using SHA1 hashing rather |
| 152 | ** than relying on file mtimes. |
| 153 | ** --header Identify the repository if there are changes |
| 154 | ** -v Say "no changes" if there are none |
| 155 | ** |
| 156 | ** See also: extra, ls, status |
| 157 | */ |
| 158 | void changes_cmd(void){ |
| 159 | Blob report; |
| 160 | int vid; |
| @@ -315,12 +315,12 @@ | |
| 315 | ** Pathnames are displayed according to the "relative-paths" setting, |
| 316 | ** unless overridden by the --abs-paths or --rel-paths options. |
| 317 | ** |
| 318 | ** Options: |
| 319 | ** --abs-paths Display absolute pathnames. |
| 320 | ** --dotfiles include files beginning with a dot (".") |
| 321 | ** --ignore <CSG> ignore files matching patterns from the |
| 322 | ** --rel-paths Display pathnames relative to the current working |
| 323 | ** directory. |
| 324 | ** |
| 325 | ** See also: changes, clean, status |
| 326 | */ |
| @@ -347,11 +347,11 @@ | |
| 347 | zIgnoreFlag = db_get("ignore-glob", 0); |
| 348 | } |
| 349 | pIgnore = glob_create(zIgnoreFlag); |
| 350 | vfile_scan(&path, blob_size(&path), scanFlags, pIgnore); |
| 351 | glob_free(pIgnore); |
| 352 | db_prepare(&q, |
| 353 | "SELECT x FROM sfile" |
| 354 | " WHERE x NOT IN (%s)" |
| 355 | " ORDER BY 1", |
| 356 | fossil_all_reserved_names() |
| 357 | ); |
| @@ -396,13 +396,13 @@ | |
| 396 | ** The GLOBPATTERN is a comma-separated list of GLOB expressions for |
| 397 | ** files that are ignored. The GLOBPATTERN specified by the "ignore-glob" |
| 398 | ** is used if the --ignore option is omitted. |
| 399 | ** |
| 400 | ** Options: |
| 401 | ** --dotfiles include files beginning with a dot (".") |
| 402 | ** --force Remove files without prompting |
| 403 | ** --ignore <CSG> ignore files matching patterns from the |
| 404 | ** comma separated list of glob patterns. |
| 405 | ** --temp Remove only Fossil-generated temporary files |
| 406 | ** |
| 407 | ** See also: addremove, extra, status |
| 408 | */ |
| @@ -427,11 +427,11 @@ | |
| 427 | n = strlen(g.zLocalRoot); |
| 428 | blob_init(&path, g.zLocalRoot, n-1); |
| 429 | pIgnore = glob_create(zIgnoreFlag); |
| 430 | vfile_scan(&path, blob_size(&path), scanFlags, pIgnore); |
| 431 | glob_free(pIgnore); |
| 432 | db_prepare(&q, |
| 433 | "SELECT %Q || x FROM sfile" |
| 434 | " WHERE x NOT IN (%s)" |
| 435 | " ORDER BY 1", |
| 436 | g.zLocalRoot, fossil_all_reserved_names() |
| 437 | ); |
| @@ -441,15 +441,17 @@ | |
| 441 | while( db_step(&q)==SQLITE_ROW ){ |
| 442 | if( allFlag ){ |
| 443 | file_delete(db_column_text(&q, 0)); |
| 444 | }else{ |
| 445 | Blob ans; |
| 446 | char cReply; |
| 447 | char *prompt = mprintf("remove unmanaged file \"%s\" (y/N)? ", |
| 448 | db_column_text(&q, 0)); |
| 449 | blob_zero(&ans); |
| 450 | prompt_user(prompt, &ans); |
| 451 | cReply = blob_str(&ans)[0]; |
| 452 | if( cReply=='y' || cReply=='Y' ){ |
| 453 | file_delete(db_column_text(&q, 0)); |
| 454 | } |
| 455 | } |
| 456 | } |
| 457 | db_finalize(&q); |
| @@ -660,11 +662,11 @@ | |
| 662 | #endif |
| 663 | } |
| 664 | |
| 665 | /* |
| 666 | ** zDate should be a valid date string. Convert this string into the |
| 667 | ** format YYYY-MM-DDTHH:MM:SS. If the string is not a valid date, |
| 668 | ** print a fatal error and quit. |
| 669 | */ |
| 670 | char *date_in_standard_format(const char *zInputDate){ |
| 671 | char *zDate; |
| 672 | if( g.perm.Setup && fossil_strcmp(zInputDate,"now")==0 ){ |
| @@ -871,11 +873,11 @@ | |
| 873 | while( db_step(&q)==SQLITE_ROW ){ |
| 874 | const char *zBrTag = db_column_text(&q, 0); |
| 875 | blob_appendf(pOut, "T -%F *\n", zBrTag); |
| 876 | } |
| 877 | db_finalize(&q); |
| 878 | } |
| 879 | blob_appendf(pOut, "U %F\n", zUserOvrd ? zUserOvrd : g.zLogin); |
| 880 | md5sum_blob(pOut, &mcksum); |
| 881 | blob_appendf(pOut, "Z %b\n", &mcksum); |
| 882 | if( pnFBcard ) *pnFBcard = nFBcard; |
| 883 | } |
| @@ -890,11 +892,10 @@ | |
| 892 | int n; /* Size of the file in bytes */ |
| 893 | int lastNl = 0; /* Characters since last \n */ |
| 894 | int i; /* Loop counter */ |
| 895 | char *zMsg; /* Warning message */ |
| 896 | Blob fname; /* Relative pathname of the file */ |
| 897 | static int allOk = 0; /* Set to true to disable this routine */ |
| 898 | |
| 899 | if( allOk ) return; |
| 900 | z = (unsigned char*)blob_buffer(p); |
| 901 | n = blob_size(p); |
| @@ -912,23 +913,25 @@ | |
| 913 | /* Binary if any line longer than 8191, see looks_like_binary() */ |
| 914 | if( lastNl>8191 ) return; |
| 915 | } |
| 916 | } |
| 917 | if( nCrNl ){ |
| 918 | Blob ans; |
| 919 | char cReply; |
| 920 | |
| 921 | file_relative_name(zFilename, &fname, 0); |
| 922 | blob_zero(&ans); |
| 923 | zMsg = mprintf( |
| 924 | "%s contains CR/NL line endings; commit anyhow (yes/no/all)?", |
| 925 | blob_str(&fname)); |
| 926 | prompt_user(zMsg, &ans); |
| 927 | fossil_free(zMsg); |
| 928 | cReply = blob_str(&ans)[0]; |
| 929 | if( cReply=='a' || cReply=='A' ){ |
| 930 | allOk = 1; |
| 931 | }else if( cReply=='y' || cReply=='Y' ){ |
| 932 | fossil_fatal("Abandoning commit due to CR/NL line endings in %s", |
| 933 | blob_str(&fname)); |
| 934 | } |
| 935 | blob_reset(&ans); |
| 936 | blob_reset(&fname); |
| 937 | } |
| @@ -949,11 +952,11 @@ | |
| 952 | ** |
| 953 | ** Usage: %fossil commit ?OPTIONS? ?FILE...? |
| 954 | ** |
| 955 | ** Create a new version containing all of the changes in the current |
| 956 | ** checkout. You will be prompted to enter a check-in comment unless |
| 957 | ** the comment has been specified on the command-line using "-m" or a |
| 958 | ** file containing the comment using -M. The editor defined in the |
| 959 | ** "editor" fossil option (see %fossil help set) will be used, or from |
| 960 | ** the "VISUAL" or "EDITOR" environment variables (in that order) if |
| 961 | ** no editor is set. |
| 962 | ** |
| @@ -993,11 +996,11 @@ | |
| 996 | ** --message-file|-M FILE read the commit comment from given file |
| 997 | ** --nosign do not attempt to sign this commit with gpg |
| 998 | ** --private do not sync changes and their descendants |
| 999 | ** --tag TAG-NAME assign given tag TAG-NAME to the checkin |
| 1000 | ** --conflict allow unresolved merge conflicts |
| 1001 | ** |
| 1002 | ** See also: branch, changes, checkout, extra, sync |
| 1003 | */ |
| 1004 | void commit_cmd(void){ |
| 1005 | int hasChanges; /* True if unsaved changes exist */ |
| 1006 | int vid; /* blob-id of parent version */ |
| @@ -1031,11 +1034,13 @@ | |
| 1034 | Blob cksum1, cksum2; /* Before and after commit checksums */ |
| 1035 | Blob cksum1b; /* Checksum recorded in the manifest */ |
| 1036 | int szD; /* Size of the delta manifest */ |
| 1037 | int szB; /* Size of the baseline manifest */ |
| 1038 | int nConflict = 0; /* Number of unresolved merge conflicts */ |
| 1039 | Blob ans; |
| 1040 | char cReply; |
| 1041 | |
| 1042 | url_proxy_options(); |
| 1043 | noSign = find_option("nosign",0,0)!=0; |
| 1044 | forceDelta = find_option("delta",0,0)!=0; |
| 1045 | forceBaseline = find_option("baseline",0,0)!=0; |
| 1046 | if( forceDelta && forceBaseline ){ |
| @@ -1095,11 +1100,10 @@ | |
| 1100 | /* |
| 1101 | ** Autosync if autosync is enabled and this is not a private check-in. |
| 1102 | */ |
| 1103 | if( !g.markPrivate ){ |
| 1104 | if( autosync(AUTOSYNC_PULL) ){ |
| 1105 | blob_zero(&ans); |
| 1106 | prompt_user("continue in spite of sync failure (y/N)? ", &ans); |
| 1107 | if( blob_str(&ans)[0]!='y' ){ |
| 1108 | fossil_exit(1); |
| 1109 | } |
| @@ -1108,14 +1112,14 @@ | |
| 1112 | |
| 1113 | /* Require confirmation to continue with the check-in if there is |
| 1114 | ** clock skew |
| 1115 | */ |
| 1116 | if( g.clockSkewSeen ){ |
| 1117 | blob_zero(&ans); |
| 1118 | prompt_user("continue in spite of time skew (y/N)? ", &ans); |
| 1119 | cReply = blob_str(&ans)[0]; |
| 1120 | if( cReply!='y' && cReply!='Y' ){ |
| 1121 | fossil_exit(1); |
| 1122 | } |
| 1123 | } |
| 1124 | |
| 1125 | /* There are two ways this command may be executed. If there are |
| @@ -1139,11 +1143,11 @@ | |
| 1143 | ** Check that the user exists. |
| 1144 | */ |
| 1145 | if( !db_exists("SELECT 1 FROM user WHERE login=%Q", g.zLogin) ){ |
| 1146 | fossil_fatal("no such user: %s", g.zLogin); |
| 1147 | } |
| 1148 | |
| 1149 | hasChanges = unsaved_changes(); |
| 1150 | db_begin_transaction(); |
| 1151 | db_record_repository_filename(0); |
| 1152 | if( hasChanges==0 && !isAMerge && !forceFlag ){ |
| 1153 | fossil_fatal("nothing has changed"); |
| @@ -1170,11 +1174,11 @@ | |
| 1174 | if( zBranch==0 && forceFlag==0 && g.markPrivate==0 && !is_a_leaf(vid) ){ |
| 1175 | fossil_fatal("would fork. \"update\" first or use -f or --force."); |
| 1176 | } |
| 1177 | |
| 1178 | /* |
| 1179 | ** Do not allow a commit against a closed leaf |
| 1180 | */ |
| 1181 | if( db_exists("SELECT 1 FROM tagxref" |
| 1182 | " WHERE tagid=%d AND rid=%d AND tagtype>0", |
| 1183 | TAG_CLOSED, vid) ){ |
| 1184 | fossil_fatal("cannot commit against a closed leaf"); |
| @@ -1190,31 +1194,31 @@ | |
| 1194 | blob_strip_bom(&comment, 1); |
| 1195 | }else{ |
| 1196 | char *zInit = db_text(0, "SELECT value FROM vvar WHERE name='ci-comment'"); |
| 1197 | prepare_commit_comment(&comment, zInit, zBranch, vid, zUserOvrd); |
| 1198 | if( zInit && zInit[0] && fossil_strcmp(zInit, blob_str(&comment))==0 ){ |
| 1199 | blob_zero(&ans); |
| 1200 | prompt_user("unchanged check-in comment. continue (y/N)? ", &ans); |
| 1201 | cReply = blob_str(&ans)[0]; |
| 1202 | if( cReply!='y' && cReply!='Y' ) fossil_exit(1);; |
| 1203 | } |
| 1204 | free(zInit); |
| 1205 | } |
| 1206 | if( blob_size(&comment)==0 ){ |
| 1207 | blob_zero(&ans); |
| 1208 | prompt_user("empty check-in comment. continue (y/N)? ", &ans); |
| 1209 | cReply = blob_str(&ans)[0]; |
| 1210 | if( cReply!='y' && cReply!='Y' ){ |
| 1211 | fossil_exit(1); |
| 1212 | } |
| 1213 | }else{ |
| 1214 | db_multi_exec("REPLACE INTO vvar VALUES('ci-comment',%B)", &comment); |
| 1215 | db_end_transaction(0); |
| 1216 | db_begin_transaction(); |
| 1217 | } |
| 1218 | |
| 1219 | /* Step 1: Insert records for all modified files into the blob |
| 1220 | ** table. If there were arguments passed to this command, only |
| 1221 | ** the identified fils are inserted (if they have been modified). |
| 1222 | */ |
| 1223 | db_prepare(&q, |
| 1224 | "SELECT id, %Q || pathname, mrid, %s, chnged FROM vfile " |
| @@ -1236,11 +1240,11 @@ | |
| 1240 | blob_zero(&content); |
| 1241 | if( file_wd_islink(zFullname) ){ |
| 1242 | /* Instead of file content, put link destination path */ |
| 1243 | blob_read_link(&content, zFullname); |
| 1244 | }else{ |
| 1245 | blob_read_from_file(&content, zFullname); |
| 1246 | } |
| 1247 | if( !crnlOk ) cr_warning(&content, zFullname); |
| 1248 | if( chnged==1 && contains_merge_marker(&content) ){ |
| 1249 | nConflict++; |
| 1250 | fossil_print("possible unresolved merge conflict in %s\n", |
| @@ -1319,20 +1323,20 @@ | |
| 1323 | }else if( forceDelta ){ |
| 1324 | fossil_panic("unable to find a baseline-manifest for the delta"); |
| 1325 | } |
| 1326 | } |
| 1327 | if( !noSign && !g.markPrivate && clearsign(&manifest, &manifest) ){ |
| 1328 | blob_zero(&ans); |
| 1329 | prompt_user("unable to sign manifest. continue (y/N)? ", &ans); |
| 1330 | cReply = blob_str(&ans)[0]; |
| 1331 | if( cReply!='y' && cReply!='Y' ){ |
| 1332 | fossil_exit(1); |
| 1333 | } |
| 1334 | } |
| 1335 | |
| 1336 | /* If the --test option is specified, output the manifest file |
| 1337 | ** and rollback the transaction. |
| 1338 | */ |
| 1339 | if( testRun ){ |
| 1340 | blob_write_to_file(&manifest, ""); |
| 1341 | } |
| 1342 | |
| @@ -1360,11 +1364,11 @@ | |
| 1364 | blob_write_to_file(&muuid, zManifestFile); |
| 1365 | free(zManifestFile); |
| 1366 | blob_reset(&muuid); |
| 1367 | } |
| 1368 | |
| 1369 | |
| 1370 | /* Update the vfile and vmerge tables */ |
| 1371 | db_multi_exec( |
| 1372 | "DELETE FROM vfile WHERE (vid!=%d OR deleted) AND is_selected(id);" |
| 1373 | "DELETE FROM vmerge;" |
| 1374 | "UPDATE vfile SET vid=%d;" |
| @@ -1384,11 +1388,11 @@ | |
| 1388 | vfile_compare_repository_to_disk(nvid); |
| 1389 | fossil_fatal("working checkout does not match what would have ended " |
| 1390 | "up in the repository: %b versus %b", |
| 1391 | &cksum1, &cksum2); |
| 1392 | } |
| 1393 | |
| 1394 | /* Verify that the manifest checksum matches the expected checksum */ |
| 1395 | vfile_aggregate_checksum_manifest(nvid, &cksum2, &cksum1b); |
| 1396 | if( blob_compare(&cksum1, &cksum1b) ){ |
| 1397 | fossil_fatal("manifest checksum self-test failed: " |
| 1398 | "%b versus %b", &cksum1, &cksum1b); |
| @@ -1396,11 +1400,11 @@ | |
| 1400 | if( blob_compare(&cksum1, &cksum2) ){ |
| 1401 | fossil_fatal( |
| 1402 | "working checkout does not match manifest after commit: " |
| 1403 | "%b versus %b", &cksum1, &cksum2); |
| 1404 | } |
| 1405 | |
| 1406 | /* Verify that the commit did not modify any disk images. */ |
| 1407 | vfile_aggregate_checksum_disk(nvid, &cksum2); |
| 1408 | if( blob_compare(&cksum1, &cksum2) ){ |
| 1409 | fossil_fatal("working checkout before and after commit does not match"); |
| 1410 | } |
| @@ -1416,11 +1420,11 @@ | |
| 1420 | exit(1); |
| 1421 | } |
| 1422 | db_end_transaction(0); |
| 1423 | |
| 1424 | if( !g.markPrivate ){ |
| 1425 | autosync(AUTOSYNC_PUSH); |
| 1426 | } |
| 1427 | if( count_nonbranch_children(vid)>1 ){ |
| 1428 | fossil_print("**** warning: a fork has occurred *****\n"); |
| 1429 | } |
| 1430 | } |
| 1431 |