Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch checkin-without-checkout Excluding Merge-Ins
This is equivalent to a diff from 44ac944a98 to 8d4ce834ed
2020-05-05
| ||
04:06 | Initial work on ajaxifying /fileedit. Fetching content, preview, and diffs are ajax'd, but save is not yet. check-in: 8edf9dbfc2 user: stephan tags: fileedit-ajaxify | |
2020-05-04
| ||
23:26 | Moved some generic fileedit code to style.c. Refactored /fileedit to not require JS to update version info, making this impl pure no-JS. Now to ajaxify it... Closed-Leaf check-in: 8d4ce834ed user: stephan tags: checkin-without-checkout | |
20:16 | Added /fileedit links to /finfo and /artifact. check-in: fe925e7d6d user: stephan tags: checkin-without-checkout | |
2020-05-03
| ||
17:46 | Wrap SSL-related features into a FOSSIL_ENABLE_SSL conditional in url.c. check-in: 0a59a82349 user: ashepilko tags: trunk | |
2020-04-30
| ||
16:14 | Merged in trunk for related changes. check-in: 03cce1c977 user: stephan tags: checkin-without-checkout | |
15:29 | Add the "forbid-delta-manifests" setting. check-in: 44ac944a98 user: drh tags: trunk | |
15:00 | Fix the file_perm() utility routine so that it actually uses the eFType parameter. check-in: 388b5e5982 user: drh tags: trunk | |
Changes to src/blob.c.
︙ | ︙ | |||
475 476 477 478 479 480 481 482 483 484 485 486 487 488 | ** nByte in size. The blob is truncated if necessary. */ void blob_resize(Blob *pBlob, unsigned int newSize){ pBlob->xRealloc(pBlob, newSize+1); pBlob->nUsed = newSize; pBlob->aData[newSize] = 0; } /* ** Make sure a blob is nul-terminated and is not a pointer to unmanaged ** space. Return a pointer to the data. */ char *blob_materialize(Blob *pBlob){ blob_resize(pBlob, pBlob->nUsed); | > > > > > > > > > > > > | 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 | ** nByte in size. The blob is truncated if necessary. */ void blob_resize(Blob *pBlob, unsigned int newSize){ pBlob->xRealloc(pBlob, newSize+1); pBlob->nUsed = newSize; pBlob->aData[newSize] = 0; } /* ** Ensures that the given blob has at least the given amount of memory ** allocated to it. Does not modify pBlob->nUsed nor will it reduce ** the currently-allocated amount of memory. */ void blob_reserve(Blob *pBlob, unsigned int newSize){ if(newSize>pBlob->nUsed){ pBlob->xRealloc(pBlob, newSize); pBlob->aData[newSize] = 0; } } /* ** Make sure a blob is nul-terminated and is not a pointer to unmanaged ** space. Return a pointer to the data. */ char *blob_materialize(Blob *pBlob){ blob_resize(pBlob, pBlob->nUsed); |
︙ | ︙ | |||
1165 1166 1167 1168 1169 1170 1171 | blob_reset(&b1); blob_reset(&b2); blob_reset(&b3); } fossil_print("ok\n"); } | < | 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 | blob_reset(&b1); blob_reset(&b2); blob_reset(&b3); } fossil_print("ok\n"); } /* ** Convert every \n character in the given blob into \r\n. */ void blob_add_cr(Blob *p){ char *z = p->aData; int j = p->nUsed; int i, n; |
︙ | ︙ | |||
1189 1190 1191 1192 1193 1194 1195 | z[j] = 0; while( j>i ){ if( (z[--j] = z[--i]) =='\n' ){ z[--j] = '\r'; } } } | < | 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 | z[j] = 0; while( j>i ){ if( (z[--j] = z[--i]) =='\n' ){ z[--j] = '\r'; } } } /* ** Remove every \r character from the given blob, replacing each one with ** a \n character if it was not already part of a \r\n pair. */ void blob_to_lf_only(Blob *p){ int i, j; |
︙ | ︙ |
Changes to src/cgi.c.
︙ | ︙ | |||
62 63 64 65 66 67 68 69 70 71 72 73 74 75 | #define PD(x,y) cgi_parameter((x),(y)) #define PT(x) cgi_parameter_trimmed((x),0) #define PDT(x,y) cgi_parameter_trimmed((x),(y)) #define PB(x) cgi_parameter_boolean(x) #define PCK(x) cgi_parameter_checked(x,1) #define PIF(x,y) cgi_parameter_checked(x,y) /* ** Destinations for output text. */ #define CGI_HEADER 0 #define CGI_BODY 1 | > > > > > > > > > > > | 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | #define PD(x,y) cgi_parameter((x),(y)) #define PT(x) cgi_parameter_trimmed((x),0) #define PDT(x,y) cgi_parameter_trimmed((x),(y)) #define PB(x) cgi_parameter_boolean(x) #define PCK(x) cgi_parameter_checked(x,1) #define PIF(x,y) cgi_parameter_checked(x,y) /* ** Shortcut for the cgi_printf() routine. Instead of using the ** ** @ ... ** ** notation provided by the translate.c utility, you can also ** optionally use: ** ** CX(...) */ #define CX cgi_printf /* ** Destinations for output text. */ #define CGI_HEADER 0 #define CGI_BODY 1 |
︙ | ︙ |
Changes to src/checkin.c.
︙ | ︙ | |||
1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 | g.aCommitFile[jj++] = ii; } g.aCommitFile[jj] = 0; bag_clear(&toCommit); } return result; } /* ** Make sure the current check-in with timestamp zDate is younger than its ** ancestor identified rid and zUuid. Throw a fatal error if not. */ static void checkin_verify_younger( int rid, /* The record ID of the ancestor */ const char *zUuid, /* The artifact ID of the ancestor */ const char *zDate /* Date & time of the current check-in */ ){ #ifndef FOSSIL_ALLOW_OUT_OF_ORDER_DATES | > > > > > > > > > > > > > > > > > > < < < < < | < < > > | 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 | g.aCommitFile[jj++] = ii; } g.aCommitFile[jj] = 0; bag_clear(&toCommit); } return result; } /* ** Returns true if the checkin identified by the first parameter is ** older than the given (valid) date/time string, else returns false. ** Also returns true if rid does not refer to a checkin, but it is not ** intended to be used for that case. */ int checkin_is_younger( int rid, /* The record ID of the ancestor */ const char *zDate /* Date & time of the current check-in */ ){ return db_exists( "SELECT 1 FROM event" " WHERE datetime(mtime)>=%Q" " AND type='ci' AND objid=%d", zDate, rid ) ? 0 : 1; } /* ** Make sure the current check-in with timestamp zDate is younger than its ** ancestor identified rid and zUuid. Throw a fatal error if not. */ static void checkin_verify_younger( int rid, /* The record ID of the ancestor */ const char *zUuid, /* The artifact ID of the ancestor */ const char *zDate /* Date & time of the current check-in */ ){ #ifndef FOSSIL_ALLOW_OUT_OF_ORDER_DATES if(checkin_is_younger(rid,zDate)==0){ fossil_fatal("ancestor check-in [%S] (%s) is not older (clock skew?)" " Use --allow-older to override.", zUuid, zDate); } #endif } /* ** zDate should be a valid date string. Convert this string into the ** format YYYY-MM-DDTHH:MM:SS. If the string is not a valid date, ** print a fatal error and quit. */ char *date_in_standard_format(const char *zInputDate){ |
︙ | ︙ | |||
2327 2328 2329 2330 2331 2332 2333 | /* ** Do not allow a commit against a closed leaf unless the commit ** ends up on a different branch. */ if( /* parent check-in has the "closed" tag... */ | < < | | 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 | /* ** Do not allow a commit against a closed leaf unless the commit ** ends up on a different branch. */ if( /* parent check-in has the "closed" tag... */ leaf_is_closed(vid) /* ... and the new check-in has no --branch option or the --branch ** option does not actually change the branch */ && (sCiInfo.zBranch==0 || db_exists("SELECT 1 FROM tagxref" " WHERE tagid=%d AND rid=%d AND tagtype>0" " AND value=%Q", TAG_BRANCH, vid, sCiInfo.zBranch)) ){ |
︙ | ︙ |
Changes to src/configure.c.
︙ | ︙ | |||
146 147 148 149 150 151 152 153 154 155 156 157 158 159 | { "dotfiles", CONFIGSET_PROJ }, { "parent-project-code", CONFIGSET_PROJ }, { "parent-project-name", CONFIGSET_PROJ }, { "hash-policy", CONFIGSET_PROJ }, { "comment-format", CONFIGSET_PROJ }, { "mimetypes", CONFIGSET_PROJ }, { "forbid-delta-manifests", CONFIGSET_PROJ }, #ifdef FOSSIL_ENABLE_LEGACY_MV_RM { "mv-rm-files", CONFIGSET_PROJ }, #endif { "ticket-table", CONFIGSET_TKT }, { "ticket-common", CONFIGSET_TKT }, | > | 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | { "dotfiles", CONFIGSET_PROJ }, { "parent-project-code", CONFIGSET_PROJ }, { "parent-project-name", CONFIGSET_PROJ }, { "hash-policy", CONFIGSET_PROJ }, { "comment-format", CONFIGSET_PROJ }, { "mimetypes", CONFIGSET_PROJ }, { "forbid-delta-manifests", CONFIGSET_PROJ }, { "fileedit-glob", CONFIGSET_PROJ }, #ifdef FOSSIL_ENABLE_LEGACY_MV_RM { "mv-rm-files", CONFIGSET_PROJ }, #endif { "ticket-table", CONFIGSET_TKT }, { "ticket-common", CONFIGSET_TKT }, |
︙ | ︙ |
Changes to src/db.c.
︙ | ︙ | |||
3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 | #if !defined(FOSSIL_ENABLE_EXEC_REL_PATHS) /* ** SETTING: exec-rel-paths boolean default=off ** When executing certain external commands (e.g. diff and ** gdiff), use relative paths. */ #endif /* ** SETTING: gdiff-command width=40 default=gdiff ** The value is an external command to run when performing a graphical ** diff. If undefined, text diff will be used. */ /* ** SETTING: gmerge-command width=40 | > > > > > > > > > | 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 | #if !defined(FOSSIL_ENABLE_EXEC_REL_PATHS) /* ** SETTING: exec-rel-paths boolean default=off ** When executing certain external commands (e.g. diff and ** gdiff), use relative paths. */ #endif /* ** SETTING: fileedit-glob width=40 block-text ** A comma- or newline-separated list of globs of filenames ** which are allowed to be edited using the /fileedit page. ** An empty list prohibits editing via that page. Note that ** it cannot edit binary files, so the glob should not ** contain any globs for, e.g., images or PDFs. */ /* ** SETTING: gdiff-command width=40 default=gdiff ** The value is an external command to run when performing a graphical ** diff. If undefined, text diff will be used. */ /* ** SETTING: gmerge-command width=40 |
︙ | ︙ |
Changes to src/default_css.txt.
︙ | ︙ | |||
858 859 860 861 862 863 864 | // border: 1px solid black; // vertical-align: top; // } // #setup_skinedit_css_defaults > tbody > tr > td:nth-of-type(2) > div { // max-width: 30em; // overflow: auto; // } | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 | // border: 1px solid black; // vertical-align: top; // } // #setup_skinedit_css_defaults > tbody > tr > td:nth-of-type(2) > div { // max-width: 30em; // overflow: auto; // } // .fileedit-XXX => /fileedit page form.fileedit textarea { font-family: monospace; width: 100%; } form.fileedit fieldset { margin: 0.5em 0 0 0; border-radius: 0.5em; border-color: inherit; border-width: 1px; } form.fileedit fieldset > legend { margin: 0 0 0 1em; padding: 0 0.5em 0 0.5em; } form.fileedit fieldset > div { margin: 0 0.25em 0.25em 0.25em; } form.fileedit fieldset > div > .input-with-label { margin: 0.25em 0.5em; } form.fileedit fieldset > div > button { margin: 0.25em 0.5em; } form.fileedit input:invalid { border-left: 0.2em dashed red; } .fileedit-hint { font-size: 80%; opacity: 0.75; } .fileedit-error-report { background: yellow; color: darkred; margin: 1em 0; padding: 0.5em; border-radius: 0.5em; } code.fileedit-manifest { display: block; height: 16em; overflow: auto; } div.fileedit-preview { margin: 0; padding: 0; } .fileedit-preview > div:first-child { margin: 1em 0 0 0; border-bottom: 1px dashed; } div.fileedit-diff { margin: 0; padding: 0; } .fileedit-diff > div:first-child { border-bottom: 1px dashed; } .input-with-label { border: 1px inset #808080; border-radius: 0.5em; padding: 0.25em 0.4em; margin: 0 0.5em; display: inline-block; cursor: pointer; } .input-with-label > * { vertical-align: middle; } .input-with-label > input { margin: 0; } .input-with-label > select { margin: 0; } .input-with-label > input[type=text] { margin: 0; } .input-with-label > textarea { margin: 0; } .input-with-label > input[type=checkbox] { vertical-align: sub; } .input-with-label > input[type=radio] { vertical-align: sub; } .input-with-label > span { margin: 0 0.25em 0 0.25em; vertical-align: middle; } |
Added src/fileedit.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 | /* ** Copyright (c) 2020 D. Richard Hipp ** ** This program is free software; you can redistribute it and/or ** modify it under the terms of the Simplified BSD License (also ** known as the "2-Clause License" or "FreeBSD License".) ** ** This program is distributed in the hope that it will be useful, ** but without any warranty; without even the implied warranty of ** merchantability or fitness for a particular purpose. ** ** Author contact information: ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ******************************************************************************* ** ** This file contains code for the /fileedit page and related code. */ #include "config.h" #include "fileedit.h" #include <assert.h> #include <stdarg.h> /* ** State for the "mini-checkin" infrastructure, which enables the ** ability to commit changes to a single file without a checkout ** db, e.g. for use via an HTTP request. ** ** Use CheckinMiniInfo_init() to cleanly initialize one to a known ** valid/empty default state. ** ** Memory for all non-const (char *) members is owned by the ** CheckinMiniInfo instance and is freed by CheckinMiniInfo_cleanup(). */ struct CheckinMiniInfo { Manifest * pParent; /* parent checkin. Memory is owned by this object. */ char *zParentUuid; /* Full UUID of pParent */ char *zFilename; /* Name of single file to commit. Must be relative to the top of the repo. */ Blob fileContent; /* Content of file referred to by zFilename. */ Blob fileHash; /* Hash of this->fileContent, using the repo's preferred hash method. */ Blob comment; /* Check-in comment text */ char *zCommentMimetype; /* Mimetype of comment. May be NULL */ char *zUser; /* User name */ char *zDate; /* Optionally force this date string (anything supported by date_in_standard_format()). Maybe be NULL. */ Blob *pMfOut; /* If not NULL, checkin_mini() will write a copy of the generated manifest here. This memory is NOT owned by CheckinMiniInfo. */ int filePerm; /* Permissions (via file_perm()) of the input file. We need to store this before calling checkin_mini() because the real input file name may differ from the repo-centric this->zFilename, and checkin_mini() requires the permissions of the original file. For web commits, set this to PERM_REG or (when editing executable scripts) PERM_EXE before calling checkin_mini(). */ int flags; /* Bitmask of fossil_cimini_flags. */ }; typedef struct CheckinMiniInfo CheckinMiniInfo; /* ** CheckinMiniInfo::flags values. */ enum fossil_cimini_flags { CIMINI_NONE = 0, /* ** Tells checkin_mini() to use dry-run mode. */ CIMINI_DRY_RUN = 1, /* ** Tells checkin_mini() to allow forking from a non-leaf commit. */ CIMINI_ALLOW_FORK = 1<<1, /* ** Tells checkin_mini() to dump its generated manifest to stdout. */ CIMINI_DUMP_MANIFEST = 1<<2, /* ** By default, content containing what appears to be a merge conflict ** marker is not permitted. This flag relaxes that requirement. */ CIMINI_ALLOW_MERGE_MARKER = 1<<3, /* ** By default mini-checkins are not allowed to be "older" ** than their parent. i.e. they may not have a timestamp ** which predates their parent. This flag bypasses that ** check. */ CIMINI_ALLOW_OLDER = 1<<4, /* ** Indicates that the content of the newly-checked-in file is ** converted, if needed, to use the same EOL style as the previous ** version of that file. Only the in-memory/in-repo copies are ** affected, not the original file (if any). */ CIMINI_CONVERT_EOL_INHERIT = 1<<5, /* ** Indicates that the input's EOLs should be converted to Unix-style. */ CIMINI_CONVERT_EOL_UNIX = 1<<6, /* ** Indicates that the input's EOLs should be converted to Windows-style. */ CIMINI_CONVERT_EOL_WINDOWS = 1<<7, /* ** A hint to checkin_mini() to "prefer" creation of a delta manifest. ** It may decide not to for various reasons. */ CIMINI_PREFER_DELTA = 1<<8, /* ** A "stronger hint" to checkin_mini() to prefer creation of a delta ** manifest if it at all can. It will decide not to only if creation ** of a delta is not a realistic option. For this to work, it must be ** set together with the CIMINI_PREFER_DELTA flag, but the two cannot ** be combined in this enum. ** ** This option is ONLY INTENDED FOR TESTING, used in bypassing ** heuristics which may otherwise disable generation of a delta on the ** grounds of efficiency (e.g. not generating a delta if the parent ** non-delta only has a few F-cards). ** ** The forbid-delta-manifests repo config option trumps this. */ CIMINI_STRONGLY_PREFER_DELTA = 1<<9, /* ** Tells checkin_mini() to permit the addition of a new file. Normally ** this is disabled because there are many cases where it could cause ** the inadvertent addition of a new file when an update to an ** existing was intended, as a side-effect of name-case differences. */ CIMINI_ALLOW_NEW_FILE = 1<<10 }; /* ** Initializes p to a known-valid default state. */ static void CheckinMiniInfo_init( CheckinMiniInfo * p ){ memset(p, 0, sizeof(CheckinMiniInfo)); p->flags = CIMINI_NONE; p->filePerm = -1; p->comment = p->fileContent = p->fileHash = empty_blob; } /* ** Frees all memory owned by p, but does not free p. */ static void CheckinMiniInfo_cleanup( CheckinMiniInfo * p ){ blob_reset(&p->comment); blob_reset(&p->fileContent); blob_reset(&p->fileHash); if(p->pParent){ manifest_destroy(p->pParent); } fossil_free(p->zFilename); fossil_free(p->zDate); fossil_free(p->zParentUuid); fossil_free(p->zCommentMimetype); fossil_free(p->zUser); CheckinMiniInfo_init(p); } /* ** Internal helper which returns an F-card perms string suitable for ** writing into a manifest. */ static const char * mfile_permint_mstring(int perm){ switch(perm){ case PERM_EXE: return " x"; case PERM_LNK: return " l"; default: return ""; } } /* ** Given a ManifestFile permission string (or NULL), it returns one of ** PERM_REG, PERM_EXE, or PERM_LNK. */ static int mfile_permstr_int(const char *zPerm){ if(!zPerm || !*zPerm) return PERM_REG; else if(strstr(zPerm,"x")) return PERM_EXE; else if(strstr(zPerm,"l")) return PERM_LNK; else return PERM_REG/*???*/; } static const char * mfile_perm_mstring(const ManifestFile * p){ return mfile_permint_mstring(manifest_file_mperm(p)); } /* ** Internal helper for checkin_mini() and friends. Appends an F-card ** for p to pOut. */ static void checkin_mini_append_fcard(Blob *pOut, const ManifestFile *p){ if(p->zUuid){ assert(*p->zUuid); blob_appendf(pOut, "F %F %s%s", p->zName, p->zUuid, mfile_perm_mstring(p)); if(p->zPrior){ assert(*p->zPrior); blob_appendf(pOut, " %F\n", p->zPrior); }else{ blob_append(pOut, "\n", 1); } }else{ /* File was removed from parent delta. */ blob_appendf(pOut, "F %F\n", p->zName); } } /* ** Handles the F-card parts for create_manifest_mini(). ** ** If asDelta is true, F-cards will be handled as for a delta ** manifest, and the caller MUST have added a B-card to pOut before ** calling this. ** ** Returns 1 on success, 0 on error, and writes any error message to ** pErr (if it's not NULL). The only non-immediately-fatal/panic error ** is if pCI->filePerm is PERM_LNK or pCI would update a PERM_LNK ** in-repo file. */ static int create_manifest_mini_fcards( Blob * pOut, CheckinMiniInfo * pCI, int asDelta, Blob * pErr){ int wroteThisCard = 0; const ManifestFile * pFile; int (*fncmp)(char const *, char const *) = /* filename comparator */ filenames_are_case_sensitive() ? fossil_strcmp : fossil_stricmp; #define mf_err(EXPR) if(pErr) blob_appendf EXPR; return 0 #define write_this_card(NAME) \ blob_appendf(pOut, "F %F %b%s\n", (NAME), &pCI->fileHash, \ mfile_permint_mstring(pCI->filePerm)); \ wroteThisCard = 1 assert(pCI->filePerm!=PERM_LNK && "This should have been validated before."); assert(pCI->filePerm==PERM_REG || pCI->filePerm==PERM_EXE); if(PERM_LNK==pCI->filePerm){ goto err_no_symlink; } manifest_file_rewind(pCI->pParent); if(asDelta!=0 && (pCI->pParent->zBaseline==0 || pCI->pParent->nFile==0)){ /* Parent is a baseline or a delta with no F-cards, so this is ** the simplest case: create a delta with a single F-card. */ pFile = manifest_file_find(pCI->pParent, pCI->zFilename); if(pFile!=0 && manifest_file_mperm(pFile)==PERM_LNK){ goto err_no_symlink; } write_this_card(pFile ? pFile->zName : pCI->zFilename); return 1; } while(1){ int cmp; if(asDelta==0){ pFile = manifest_file_next(pCI->pParent, 0); }else{ /* Parent is a delta manifest with F-cards. Traversal of delta ** manifest file entries is normally done via ** manifest_file_next(), which takes into account the ** differences between the delta and its parent and returns ** F-cards from both. Each successive delta from the same ** baseline includes all F-card changes from the previous ** deltas, so we instead clone the parent's F-cards except for ** the one (if any) which matches the new file. */ pFile = pCI->pParent->iFile < pCI->pParent->nFile ? &pCI->pParent->aFile[pCI->pParent->iFile++] : 0; } if(0==pFile) break; cmp = fncmp(pFile->zName, pCI->zFilename); if(cmp<0){ checkin_mini_append_fcard(pOut,pFile); }else{ if(cmp==0 || 0==wroteThisCard){ assert(0==wroteThisCard); if(PERM_LNK==manifest_file_mperm(pFile)){ goto err_no_symlink; } write_this_card(cmp==0 ? pFile->zName : pCI->zFilename); } if(cmp>0){ assert(wroteThisCard!=0); checkin_mini_append_fcard(pOut,pFile); } } } if(wroteThisCard==0){ write_this_card(pCI->zFilename); } return 1; err_no_symlink: mf_err((pErr,"Cannot commit or overwrite symlinks " "via mini-checkin.")); return 0; #undef write_this_card #undef mf_err } /* ** Creates a manifest file, written to pOut, from the state in the ** fully-populated and semantically valid pCI argument. pCI is not ** *semantically* modified but cannot be const because blob_str() may ** need to NUL-terminate any given blob. ** ** Returns true on success. On error, returns 0 and, if pErr is not ** NULL, writes an error message there. ** ** Intended only to be called via checkin_mini() or routines which ** have already completely vetted pCI. */ static int create_manifest_mini( Blob * pOut, CheckinMiniInfo * pCI, Blob * pErr){ Blob zCard = empty_blob; /* Z-card checksum */ int asDelta = 0; #define mf_err(EXPR) if(pErr) blob_appendf EXPR; return 0 assert(blob_str(&pCI->fileHash)); assert(pCI->pParent); assert(pCI->zFilename); assert(pCI->zUser); assert(pCI->zDate); /* Potential TODOs include... ** ** - Maybe add support for tags. Those can be edited via /info page, ** and feel like YAGNI/feature creep for this purpose. */ blob_zero(pOut); manifest_file_rewind(pCI->pParent) /* force load of baseline */; /* Determine whether we want to create a delta manifest... */ if((CIMINI_PREFER_DELTA & pCI->flags) && ((CIMINI_STRONGLY_PREFER_DELTA & pCI->flags) || (pCI->pParent->pBaseline ? pCI->pParent->pBaseline : pCI->pParent)->nFile > 15 /* 15 is arbitrary: don't create a delta when there is only a ** tiny gain for doing so. That heuristic is not *quite* ** right, in that when we're deriving from another delta, we ** really should compare the F-card count between it and its ** baseline, and create a delta if the baseline has (say) ** twice or more as many F-cards as the previous delta. */) && !db_get_boolean("forbid-delta-manifests",0) ){ asDelta = 1; blob_appendf(pOut, "B %s\n", pCI->pParent->zBaseline ? pCI->pParent->zBaseline : pCI->zParentUuid); } blob_reserve(pOut, 1024 * (asDelta ? 2 : pCI->pParent->nFile/11+1 /* In the fossil core repo, each 12-ish F-cards (on ** average) take up roughly 1kb */)); if(blob_size(&pCI->comment)!=0){ blob_appendf(pOut, "C %F\n", blob_str(&pCI->comment)); }else{ blob_append(pOut, "C (no\\scomment)\n", 16); } blob_appendf(pOut, "D %s\n", pCI->zDate); if(create_manifest_mini_fcards(pOut,pCI,asDelta,pErr)==0){ return 0; } if(pCI->zCommentMimetype!=0 && pCI->zCommentMimetype[0]!=0){ blob_appendf(pOut, "N %F\n", pCI->zCommentMimetype); } blob_appendf(pOut, "P %s\n", pCI->zParentUuid); blob_appendf(pOut, "U %F\n", pCI->zUser); md5sum_blob(pOut, &zCard); blob_appendf(pOut, "Z %b\n", &zCard); blob_reset(&zCard); return 1; #undef mf_err } /* ** EXPERIMENTAL! Subject to change or removal at any time. ** ** A so-called "single-file/mini/web checkin" is a slimmed-down form ** of the checkin command which accepts only a single file and is ** intended to accept edits to a file via the web interface or from ** the CLI from outside of a checkout. ** ** Being fully non-interactive is a requirement for this function, ** thus it cannot perform autosync or similar activities. ** ** This routine uses the state from the given fully-populated pCI ** argument to add pCI->fileContent to the database, and create and ** save a manifest for that change. Ownership of pCI and its contents ** are unchanged. ** ** This function may may modify pCI as follows: ** ** - If one of Manifest pCI->pParent or pCI->zParentUuid are NULL, ** then the other will be assigned based on its counterpart. Both ** may not be NULL. ** ** - pCI->zDate is normalized to/replaced with a valid date/time ** string. If its original value cannot be validated then ** this function fails. If pCI->zDate is NULL, the current time ** is used. ** ** - If the CIMINI_CONVERT_EOL_INHERIT flag is set, ** pCI->fileContent appears to be plain text, and its line-ending ** style differs from its previous version, it is converted to the ** same EOL style as the previous version. If this is done, the ** pCI->fileHash is re-computed. Note that only pCI->fileContent, ** not the original file, is affected by the conversion. ** ** - If pCI->fileHash is empty, this routine populates it with the ** repository's preferred hash algorithm. ** ** - pCI->comment may be converted to Unix-style newlines. ** ** pCI's ownership is not modified. ** ** This function validates several of the inputs and fails if any ** validation fails. ** ** On error, returns false (0) and, if pErr is not NULL, writes a ** diagnostic message there. ** ** Returns true on success. If pRid is not NULL, the RID of the ** resulting manifest is written to *pRid. ** ** The checkin process is largely influenced by pCI->flags, and that ** must be populated before calling this. See the fossil_cimini_flags ** enum for the docs for each flag. */ static int checkin_mini(CheckinMiniInfo * pCI, int *pRid, Blob * pErr){ Blob mf = empty_blob; /* output manifest */ int rid = 0, frid = 0; /* various RIDs */ int isPrivate; /* whether this is private content or not */ ManifestFile * zFilePrev; /* file entry from pCI->pParent */ int prevFRid = 0; /* RID of file's prev. version */ #define ci_err(EXPR) if(pErr!=0){blob_appendf EXPR;} goto ci_error if(!(pCI->flags & CIMINI_DRY_RUN)){ /* Until this feature is fully vetted, disallow it in the main ** fossil repo unless dry-run mode is being used. */ char * zProjCode = db_get("project-code",0); assert(zProjCode); if(0==fossil_stricmp("CE59BB9F186226D80E49D1FA2DB29F935CCA0333", zProjCode)){ fossil_fatal("Never, ever run this in/on the core fossil repo " "in non-dry-run mode until it's been well-vetted. " "Use a temp/test repo."); } fossil_free(zProjCode); } db_begin_transaction(); if(pCI->pParent==0 && pCI->zParentUuid==0){ ci_err((pErr, "Cannot determine parent version.")); } else if(pCI->pParent==0){ pCI->pParent = manifest_get_by_name(pCI->zParentUuid, 0); if(pCI->pParent==0){ ci_err((pErr,"Cannot load manifest for [%S].", pCI->zParentUuid)); } }else if(pCI->zParentUuid==0){ pCI->zParentUuid = rid_to_uuid(pCI->pParent->rid); assert(pCI->zParentUuid); } assert(pCI->pParent->rid>0); if(leaf_is_closed(pCI->pParent->rid)){ ci_err((pErr,"Cannot commit to a closed leaf.")); /* Remember that in order to override this we'd also need to ** cancel TAG_CLOSED on pCI->pParent. There would seem to be no ** reason we can't do that via the generated manifest, but the ** commit command does not offer that option, so mini-checkin ** probably shouldn't, either. */ } if( !db_exists("SELECT 1 FROM user WHERE login=%Q", pCI->zUser) ){ ci_err((pErr,"No such user: %s", pCI->zUser)); } if(!(CIMINI_ALLOW_FORK & pCI->flags) && !is_a_leaf(pCI->pParent->rid)){ ci_err((pErr,"Parent [%S] is not a leaf and forking is disabled.", pCI->zParentUuid)); } if(!(CIMINI_ALLOW_MERGE_MARKER & pCI->flags) && contains_merge_marker(&pCI->fileContent)){ ci_err((pErr,"Content appears to contain a merge conflict marker.")); } if(!file_is_simple_pathname(pCI->zFilename, 1)){ ci_err((pErr,"Invalid filename for use in a repository: %s", pCI->zFilename)); } if(!(CIMINI_ALLOW_OLDER & pCI->flags) && !checkin_is_younger(pCI->pParent->rid, pCI->zDate)){ ci_err((pErr,"Checkin time (%s) may not be older " "than its parent (%z).", pCI->zDate, db_text(0, "SELECT strftime('%%Y-%%m-%%dT%%H:%%M:%%f',%lf)", pCI->pParent->rDate) )); } { /* ** Normalize the timestamp. We don't use date_in_standard_format() ** because that has side-effects we don't want to trigger here. */ char * zDVal = db_text( 0, "SELECT strftime('%%Y-%%m-%%dT%%H:%%M:%%f',%Q)", pCI->zDate ? pCI->zDate : "now"); if(zDVal==0 || zDVal[0]==0){ fossil_free(zDVal); ci_err((pErr,"Invalid timestamp string: %s", pCI->zDate)); } fossil_free(pCI->zDate); pCI->zDate = zDVal; } { /* Confirm that only one EOL policy is in place. */ int n = 0; if(CIMINI_CONVERT_EOL_INHERIT & pCI->flags) ++n; if(CIMINI_CONVERT_EOL_UNIX & pCI->flags) ++n; if(CIMINI_CONVERT_EOL_WINDOWS & pCI->flags) ++n; if(n>1){ ci_err((pErr,"More than 1 EOL conversion policy was specified.")); } } /* Potential TODOs include: ** ** - Commit allows an empty checkin only with a flag, but we ** currently disallow it entirely. Conform with commit? ** ** Non-TODOs: ** ** - Check for a commit lock would require auto-sync, which this ** code cannot do if it's going to be run via a web page. */ /* ** Confirm that pCI->zFilename can be found in pCI->pParent. If ** not, fail unless the CIMINI_ALLOW_NEW_FILE flag is set. This is ** admittedly an artificial limitation, not strictly necessary. We ** do it to hopefully reduce the chance of an "oops" where file ** X/Y/z gets committed as X/Y/Z or X/y/z due to a typo or ** case-sensitivity mismatch between the user/repo/filesystem, or ** some such. */ manifest_file_rewind(pCI->pParent); zFilePrev = manifest_file_find(pCI->pParent, pCI->zFilename); if(!(CIMINI_ALLOW_NEW_FILE & pCI->flags) && (!zFilePrev || !zFilePrev->zUuid/*was removed from parent delta manifest*/) ){ ci_err((pErr,"File [%s] not found in manifest [%S]. " "Adding new files is currently not permitted.", pCI->zFilename, pCI->zParentUuid)); }else if(zFilePrev && manifest_file_mperm(zFilePrev)==PERM_LNK){ ci_err((pErr,"Cannot save a symlink via a mini-checkin.")); } if(zFilePrev){ prevFRid = fast_uuid_to_rid(zFilePrev->zUuid); } if(((CIMINI_CONVERT_EOL_INHERIT & pCI->flags) || (CIMINI_CONVERT_EOL_UNIX & pCI->flags) || (CIMINI_CONVERT_EOL_WINDOWS & pCI->flags)) && blob_size(&pCI->fileContent)>0 ){ /* Convert to the requested EOL style. Note that this inherently ** runs a risk of breaking content, e.g. string literals which ** contain embedded newlines. Note that HTML5 specifies that ** form-submitted TEXTAREA content gets normalized to CRLF-style: ** ** https://html.spec.whatwg.org/multipage/form-elements.html#the-textarea-element */ const int pseudoBinary = LOOK_LONG | LOOK_NUL; const int lookFlags = LOOK_CRLF | pseudoBinary; const int lookNew = looks_like_utf8( &pCI->fileContent, lookFlags ); if(!(pseudoBinary & lookNew)){ int rehash = 0; if(CIMINI_CONVERT_EOL_INHERIT & pCI->flags){ Blob contentPrev = empty_blob; int lookOrig, nOrig; content_get(prevFRid, &contentPrev); lookOrig = looks_like_utf8(&contentPrev, lookFlags); nOrig = blob_size(&contentPrev); blob_reset(&contentPrev); if(nOrig>0 && lookOrig!=lookNew){ /* If there is a newline-style mismatch, adjust the new ** content version to the previous style, then re-hash the ** content. Note that this means that what we insert is NOT ** what's in the filesystem. */ if(!(lookOrig & LOOK_CRLF) && (lookNew & LOOK_CRLF)){ /* Old has Unix-style, new has Windows-style. */ blob_to_lf_only(&pCI->fileContent); rehash = 1; }else if((lookOrig & LOOK_CRLF) && !(lookNew & LOOK_CRLF)){ /* Old has Windows-style, new has Unix-style. */ blob_add_cr(&pCI->fileContent); rehash = 1; } } }else{ const int oldSize = blob_size(&pCI->fileContent); if(CIMINI_CONVERT_EOL_UNIX & pCI->flags){ blob_to_lf_only(&pCI->fileContent); }else{ assert(CIMINI_CONVERT_EOL_WINDOWS & pCI->flags); blob_add_cr(&pCI->fileContent); } if(blob_size(&pCI->fileContent)!=oldSize){ rehash = 1; } } if(rehash!=0){ hname_hash(&pCI->fileContent, 0, &pCI->fileHash); } } }/* end EOL conversion */ if(blob_size(&pCI->fileHash)==0){ /* Hash the content if it's not done already... */ hname_hash(&pCI->fileContent, 0, &pCI->fileHash); assert(blob_size(&pCI->fileHash)>0); } if(zFilePrev){ /* Has this file been changed since its previous commit? Note ** that we have to delay this check until after the potentially ** expensive EOL conversion. */ assert(blob_size(&pCI->fileHash)); if(0==fossil_strcmp(zFilePrev->zUuid, blob_str(&pCI->fileHash)) && manifest_file_mperm(zFilePrev)==pCI->filePerm){ ci_err((pErr,"File is unchanged. Not saving.")); } } #if 1 /* Do we really want to normalize comment EOLs? Web-posting will ** submit them in CRLF format. */ blob_to_lf_only(&pCI->comment); #endif /* Create, save, deltify, and crosslink the manifest... */ if(create_manifest_mini(&mf, pCI, pErr)==0){ return 0; } isPrivate = content_is_private(pCI->pParent->rid); rid = content_put_ex(&mf, 0, 0, 0, isPrivate); if(pCI->flags & CIMINI_DUMP_MANIFEST){ fossil_print("%b", &mf); } if(pCI->pMfOut!=0){ /* Cross-linking clears mf, so we have to copy it, ** instead of taking over its memory. */ blob_reset(pCI->pMfOut); blob_append(pCI->pMfOut, blob_buffer(&mf), blob_size(&mf)); } content_deltify(rid, &pCI->pParent->rid, 1, 0); manifest_crosslink(rid, &mf, 0); blob_reset(&mf); /* Save and deltify the file content... */ frid = content_put_ex(&pCI->fileContent, blob_str(&pCI->fileHash), 0, 0, isPrivate); if(zFilePrev!=0){ assert(prevFRid>0); content_deltify(frid, &prevFRid, 1, 0); } db_end_transaction((CIMINI_DRY_RUN & pCI->flags) ? 1 : 0); if(pRid!=0){ *pRid = rid; } return 1; ci_error: assert(db_transaction_nesting_depth()>0); db_end_transaction(1); return 0; #undef ci_err } /* ** COMMAND: test-ci-mini ** ** This is an on-going experiment, subject to change or removal at ** any time. ** ** Usage: %fossil test-ci-mini ?OPTIONS? FILENAME ** ** where FILENAME is a repo-relative name as it would appear in the ** vfile table. ** ** Options: ** ** --repository|-R REPO The repository file to commit to. ** --as FILENAME The repository-side name of the input ** file, relative to the top of the ** repository. Default is the same as the ** input file name. ** --comment|-m COMMENT Required checkin comment. ** --comment-file|-M FILE Reads checkin comment from the given file. ** --revision|-r VERSION Commit from this version. Default is ** the checkout version (if available) or ** trunk (if used without a checkout). ** --allow-fork Allows the commit to be made against a ** non-leaf parent. Note that no autosync ** is performed beforehand. ** --allow-merge-conflict Allows checkin of a file even if it ** appears to contain a fossil merge conflict ** marker. ** --user-override USER USER to use instead of the current ** default. ** --date-override DATETIME DATE to use instead of 'now'. ** --allow-older Allow a commit to be older than its ** ancestor. ** --convert-eol Convert EOL style of the checkin to match ** the previous version's content. Does not ** modify the input file, only the checked-in ** content. ** --delta Prefer to generate a delta manifest, if ** able. The forbid-delta-manifests repo ** config option trumps this, as do certain ** heuristics. ** --allow-new-file Allow addition of a new file this way. ** Disabled by default to avoid that case- ** sensitivity errors inadvertently lead to ** adding a new file where an update is ** intended. ** --dump-manifest|-d Dumps the generated manifest to stdout ** immediately after it's generated. ** --save-manifest FILE Saves the generated manifest to a file ** after successfully processing it. ** --wet-run Disables the default dry-run mode. ** ** Example: ** ** %fossil test-ci-mini -R REPO -m ... -r foo --as src/myfile.c myfile.c ** */ void test_ci_mini_cmd(){ CheckinMiniInfo cimi; /* checkin state */ int newRid = 0; /* RID of new version */ const char * zFilename; /* argv[2] */ const char * zComment; /* -m comment */ const char * zCommentFile; /* -M FILE */ const char * zAsFilename; /* --as filename */ const char * zRevision; /* --revision|-r [=trunk|checkout] */ const char * zUser; /* --user-override */ const char * zDate; /* --date-override */ char const * zManifestFile = 0;/* --save-manifest FILE */ /* This function should perform only the minimal "business logic" it ** needs in order to fully/properly populate the CheckinMiniInfo and ** then pass it on to checkin_mini() to do most of the validation ** and work. The point of this is to avoid duplicate code when a web ** front-end is added for checkin_mini(). */ CheckinMiniInfo_init(&cimi); zComment = find_option("comment","m",1); zCommentFile = find_option("comment-file","M",1); zAsFilename = find_option("as",0,1); zRevision = find_option("revision","r",1); zUser = find_option("user-override",0,1); zDate = find_option("date-override",0,1); zManifestFile = find_option("save-manifest",0,1); if(find_option("wet-run",0,0)==0){ cimi.flags |= CIMINI_DRY_RUN; } if(find_option("allow-fork",0,0)!=0){ cimi.flags |= CIMINI_ALLOW_FORK; } if(find_option("dump-manifest","d",0)!=0){ cimi.flags |= CIMINI_DUMP_MANIFEST; } if(find_option("allow-merge-conflict",0,0)!=0){ cimi.flags |= CIMINI_ALLOW_MERGE_MARKER; } if(find_option("allow-older",0,0)!=0){ cimi.flags |= CIMINI_ALLOW_OLDER; } if(find_option("convert-eol-prev",0,0)!=0){ cimi.flags |= CIMINI_CONVERT_EOL_INHERIT; } if(find_option("delta",0,0)!=0){ cimi.flags |= CIMINI_PREFER_DELTA; } if(find_option("delta2",0,0)!=0){ /* Undocumented. For testing only. */ cimi.flags |= CIMINI_PREFER_DELTA | CIMINI_STRONGLY_PREFER_DELTA; } if(find_option("allow-new-file",0,0)!=0){ cimi.flags |= CIMINI_ALLOW_NEW_FILE; } db_find_and_open_repository(0, 0); verify_all_options(); user_select(); if(g.argc!=3){ usage("INFILE"); } if(zComment && zCommentFile){ fossil_fatal("Only one of -m or -M, not both, may be used."); }else{ if(zCommentFile && *zCommentFile){ blob_read_from_file(&cimi.comment, zCommentFile, ExtFILE); }else if(zComment && *zComment){ blob_append(&cimi.comment, zComment, -1); } if(!blob_size(&cimi.comment)){ fossil_fatal("Non-empty checkin comment is required."); } } db_begin_transaction(); zFilename = g.argv[2]; cimi.zFilename = mprintf("%/", zAsFilename ? zAsFilename : zFilename); cimi.filePerm = file_perm(zFilename, ExtFILE); cimi.zUser = mprintf("%s", zUser ? zUser : login_name()); if(zDate){ cimi.zDate = mprintf("%s", zDate); } if(zRevision==0 || zRevision[0]==0){ if(g.localOpen/*checkout*/){ zRevision = db_lget("checkout-hash", 0)/*leak*/; }else{ zRevision = "trunk"; } } name_to_uuid2(zRevision, "ci", &cimi.zParentUuid); if(cimi.zParentUuid==0){ fossil_fatal("Cannot determine version to commit to."); } blob_read_from_file(&cimi.fileContent, zFilename, ExtFILE); { Blob theManifest = empty_blob; /* --save-manifest target */ Blob errMsg = empty_blob; int rc; if(zManifestFile){ cimi.pMfOut = &theManifest; } rc = checkin_mini(&cimi, &newRid, &errMsg); if(rc){ assert(blob_size(&errMsg)==0); }else{ assert(blob_size(&errMsg)); fossil_fatal("%b", &errMsg); } if(zManifestFile){ fossil_print("Writing manifest to: %s\n", zManifestFile); assert(blob_size(&theManifest)>0); blob_write_to_file(&theManifest, zManifestFile); blob_reset(&theManifest); } } if(newRid!=0){ fossil_print("New version%s: %z\n", (cimi.flags & CIMINI_DRY_RUN) ? " (dry run)" : "", rid_to_uuid(newRid)); } db_end_transaction(0/*checkin_mini() will have triggered it to roll ** back in dry-run mode, but we need access to ** the transaction-written db state in this ** routine.*/); if(!(cimi.flags & CIMINI_DRY_RUN) && newRid!=0 && g.localOpen!=0){ fossil_warning("The checkout state is now out of sync " "with regards to this commit. It needs to be " "'update'd or 'close'd and re-'open'ed."); } CheckinMiniInfo_cleanup(&cimi); } /* ** Returns true if the given filename qualifies for online editing by ** the current user, else returns false. ** ** Editing requires that the user have the Write permission and that ** the filename match the glob defined by the fileedit-glob setting. ** A missing or empty value for that glob disables all editing. */ int fileedit_is_editable(const char *zFilename){ static Glob * pGlobs = 0; static int once = 0; if(0==g.perm.Write || zFilename==0 || *zFilename==0 || (once!=0 && pGlobs==0)){ return 0; }else if(0==pGlobs){ char * zGlobs = db_get("fileedit-glob",0); once = 1; if(0==zGlobs) return 0; pGlobs = glob_create(zGlobs); fossil_free(zGlobs); } return glob_match(pGlobs, zFilename); } /* ** Emits a script tag which defines window.fossil.fetch(), which works ** similarly (not identically) to the not-quite-ubiquitous global ** fetch(). ** ** JS usages: ** ** fossilFetch( URI, onLoadCallback ); ** ** fossilFetch( URI, optionsObject ); ** ** Noting that URI must be relative to the top of the repository and ** must not start with a slash (if it does, it is stripped). It gets ** %R/ prepended to it. ** ** The optionsObject may be an onload callback or an object with any ** of these properties: ** ** - onload: callback(responseData) (default = output response to ** console). ** ** - onerror: callback(XHR onload event) (default = console output) ** ** - method: 'POST' | 'GET' (default = 'GET') ** ** - payload: anything acceptable by XHR2.send(ARG) (DOMString, ** Document, FormData, Blob, File, ArrayBuffer), or a plain object ** or array, either of which gets JSON.stringify()'d. If set then ** the method is automatically set to 'POST'. If an object/array is ** converted to JSON, the content-type is set to 'application/json'. ** By default XHR2 will set the content type based on the payload ** type. ** ** - contentType: Optional request content type when POSTing. Ignored ** if the method is not 'POST'. ** ** - responseType: optional string. One of ("text", "arraybuffer", ** "blob", or "document") (as specified by XHR2). Default = "text". ** ** - urlParams: string|object. If a string, it is assumed to be a ** URI-encoded list of params in the form "key1=val1&key2=val2...", ** with NO leading '?'. If it is an object, all of its properties ** get converted to that form. Either way, the parameters get ** appended to the URL. ** */ void fileedit_emit_script_fetch(){ style_emit_script_tag(0); CX("fossil.fetch = function(path,opt){\n"); CX(" if('/'===path[0]) path = path.substr(1);\n"); CX(" if(!opt){\n"); CX(" opt = {onload:(r)=>console.debug('response:',r)};\n"); CX(" }else if('function'===typeof opt){\n"); CX(" opt={onload:opt,\n"); CX(" onerror:(e)=>console.error('ajax error:',e)};\n"); CX(" }\n"); CX(" let payload = opt.payload;\n"); CX(" if(payload){\n"); CX(" opt.method = 'POST';\n"); CX(" if(!(payload instanceof FormData)\n"); CX(" && !(payload instanceof Document)\n"); CX(" && !(payload instanceof Blob)\n"); CX(" && !(payload instanceof File)\n"); CX(" && !(payload instanceof ArrayBuffer)){\n"); CX(" if('object'===typeof payload || payload instanceof Array){\n"); CX(" payload = JSON.stringify(payload);\n"); CX(" opt.contentType = 'application/json';\n"); CX(" }\n"); CX(" }\n"); CX(" }\n"); CX(" const url=['%R/'+path], x=new XMLHttpRequest();\n"); CX(" if(opt.urlParams){\n"); CX(" url.push('?');\n"); CX(" if('string'===typeof opt.urlParams){\n"); CX(" url.push(opt.urlParams);\n"); CX(" }else{/*assume object*/\n"); CX(" let k, i = 0;\n"); CX(" for( k in opt.urlParams ){\n"); CX(" if(i++) url.push('&');\n"); CX(" url.push(k,'=',encodeURIComponent(opt.urlParams[k]));\n"); CX(" }\n"); CX(" }\n"); CX(" }\n"); CX(" if('POST'===opt.method && 'string'===typeof opt.contentType){\n"); CX(" x.setRequestHeader('Content-Type',opt.contentType);\n"); CX(" }\n"); CX(" x.open(opt.method||'GET', url.join(''), true);\n"); CX(" x.responseType=opt.responseType||'text';\n"); CX(" if(opt.onload){\n"); CX(" x.onload = function(e){\n"); CX(" if(200!==this.status){\n"); CX(" if(opt.onerror) opt.onerror(e);\n"); CX(" return;\n"); CX(" }\n"); CX(" opt.onload(this.response);\n"); CX(" }\n"); CX(" }\n"); CX(" if(payload) x.send(payload);\n"); CX(" else x.send();\n"); CX("};\n"); style_emit_script_tag(1); }; enum fileedit_render_preview_flags { FE_PREVIEW_LINE_NUMBERS = 1 }; enum fileedit_render_modes { FE_RENDER_GUESS = 0, FE_RENDER_PLAIN_TEXT, FE_RENDER_HTML, FE_RENDER_WIKI }; static int fileedit_render_mode_for_mimetype(const char * zMimetype){ int rc = FE_RENDER_PLAIN_TEXT; if( zMimetype ){ if( fossil_strcmp(zMimetype, "text/html")==0 ){ rc = FE_RENDER_HTML; }else if( fossil_strcmp(zMimetype, "text/x-fossil-wiki")==0 || fossil_strcmp(zMimetype, "text/x-markdown")==0 ){ rc = FE_RENDER_WIKI; } } return rc; } /* ** Performs the PREVIEW mode for /filepage. */ static void fileedit_render_preview(Blob * pContent, const char *zFilename, int flags, int renderMode, int nIframeHeightEm){ const char * zMime; zMime = mimetype_from_name(zFilename); if(FE_RENDER_GUESS==renderMode){ renderMode = fileedit_render_mode_for_mimetype(zMime); } CX("<div class='fileedit-preview'>"); CX("<div>Preview</div>"); switch(renderMode){ case FE_RENDER_HTML:{ char * z64 = encode64(blob_str(pContent), blob_size(pContent)); CX("<iframe width='100%%' frameborder='0' " "marginwidth='0' style='height:%dem' " "marginheight='0' sandbox='allow-same-origin' " "id='ifm1' src='data:text/html;base64,%z'" "></iframe>", nIframeHeightEm ? nIframeHeightEm : 40, z64); break; } case FE_RENDER_WIKI: wiki_render_by_mimetype(pContent, zMime); break; default:{ const char *zExt = strrchr(zFilename,'.'); const char *zContent = blob_str(pContent); if(FE_PREVIEW_LINE_NUMBERS & flags){ output_text_with_line_numbers(zContent, "on"); }else if(zExt && zExt[1]){ CX("<pre><code class='language-%s'>%h</code></pre>", zExt+1, zContent); }else{ CX("<pre>%h</pre>", zExt+1, zContent); } break; } } CX("</div><!--.fileedit-preview-->\n"); } /* ** Renders diffs for the /fileedit page. pContent is the ** locally-edited content. frid is the RID of the file's blob entry ** from which pContent is based. zManifestUuid is the checkin version ** to which RID belongs - it is purely informational, for labeling the ** diff view. isSbs is true for side-by-side diffs, false for unified. */ static void fileedit_render_diff(Blob * pContent, int frid, const char * zManifestUuid, int isSbs){ Blob orig = empty_blob; Blob out = empty_blob; u64 diffFlags = DIFF_HTML | DIFF_NOTTOOBIG | DIFF_STRIP_EOLCR | (isSbs ? DIFF_SIDEBYSIDE : DIFF_LINENO); content_get(frid, &orig); text_diff(&orig, pContent, &out, 0, diffFlags); CX("<div class='fileedit-diff'>"); CX("<div>Diff <code>[%S]</code> → Local Edits</div>", zManifestUuid); if(isSbs){ CX("%b",&out); }else{ CX("<pre class='udiff'>%b</pre>",&out); } CX("</div><!--.fileedit-diff-->\n"); blob_reset(&orig); blob_reset(&out); } /* ** Given a repo-relative filename and a manifest RID, returns the UUID ** of the corresponding file entry. Returns NULL if no match is ** found. If pFilePerm is not NULL, the file's permission flag value ** is written to *pFilePerm. */ static char *fileedit_file_uuid(char const *zFilename, int vid, int *pFilePerm){ Stmt stmt = empty_Stmt; char * zFileUuid = 0; db_prepare(&stmt, "SELECT uuid, perm FROM files_of_checkin " "WHERE filename=%Q %s AND checkinID=%d", zFilename, filename_collation(), vid); if(SQLITE_ROW==db_step(&stmt)){ zFileUuid = mprintf("%s",db_column_text(&stmt, 0)); if(pFilePerm){ *pFilePerm = mfile_permstr_int(db_column_text(&stmt, 1)); } } db_finalize(&stmt); return zFileUuid; } /* ** WEBPAGE: fileedit ** ** EXPERIMENTAL and subject to change and removal at any time. The goal ** is to allow online edits of files. ** ** Query parameters: ** ** file=FILENAME Repo-relative path to the file. ** r=VERSION Checkin version, using any unambiguous ** supported symbolic version name. ** ** All other parameters are for internal use only, submitted via the ** form-submission process, and may change with any given revision of ** this code. */ void fileedit_page(){ enum submit_modes { SUBMIT_NONE = 0, SUBMIT_SAVE, SUBMIT_PREVIEW, SUBMIT_DIFF_SBS, SUBMIT_DIFF_UNIFIED, SUBMIT_end /* sentinel for range validation */ }; const char * zFilename = PD("file",P("name")); /* filename. We'll accept 'name' because that param is handled specially by the core. */ const char * zRev = P("r"); /* checkin version */ const char * zContent = P("content"); /* file content */ const char * zComment = P("comment"); /* checkin comment */ const char * zFileMime = 0; /* File mime type guess */ CheckinMiniInfo cimi; /* Checkin state */ int submitMode = SUBMIT_NONE; /* See mapping below */ int vid, newVid = 0; /* checkin rid */ int frid = 0; /* File content rid */ int previewLn = P("preview_ln")!=0; /* Line number mode */ int previewHtmlHeight = 0; /* iframe height (EMs) */ int previewRenderMode = FE_RENDER_GUESS; /* preview mode */ char * zFileUuid = 0; /* File content UUID */ Blob err = empty_blob; /* Error report */ Blob submitResult = empty_blob; /* Error report */ const char * zFlagCheck = 0; /* Temp url flag holder */ Blob endScript = empty_blob; /* Script code to run at the end. This content will be combined into a single JS function call, thus each entry must end with a semicolon. */ Stmt stmt = empty_Stmt; const int loadMode = 0; /* See next comment block */ /* loadMode: How to populate the TEXTAREA: ** ** 0: HTML encode: despite my personal reservations regarding HTML ** escaping, this seems to be the only reliable approach ** until/unless we completely AJAXify this page. ** ** 1: JSON mode: JSON-izes the file content and injects it, via JS, ** into the editor TEXTAREA. This works wonderfully until the input ** file contains an raw <SCRIPT> tag, at which points the HTML ** parser chokes on it. ** ** 2: AJAX mode: can only load content from the db, not preview/dry-run ** content. Unless this page is refactored to work solely over AJAX ** (which is a potential TODO), this method is only useful on the ** initial hit to this page, where the file is loaded. ** ** loadMode is not generally configurable: change it only for ** testing/development purposes. */ #define fail(EXPR) blob_appendf EXPR; goto end_footer assert(loadMode==0 || loadMode==1 || loadMode==2); login_check_credentials(); if( !g.perm.Write ){ login_needed(g.anon.Write); return; } db_begin_transaction(); CheckinMiniInfo_init(&cimi); submitMode = atoi(PD("submit","0")); if(submitMode < SUBMIT_NONE || submitMode >= SUBMIT_end){ submitMode = 0; } zFlagCheck = P("comment_mimetype"); if(zFlagCheck){ cimi.zCommentMimetype = mprintf("%s",zFlagCheck); zFlagCheck = 0; } cimi.zUser = mprintf("%s",g.zLogin); style_header("File Editor"); /* As of this point, don't use return or fossil_fatal(), use ** fail((&err,...)) instead so that we can be sure to do any ** cleanup and end the transaction cleanly. */ if(!zRev || !*zRev || !zFilename || !*zFilename){ fail((&err,"Missing required URL parameters: " "file=FILE and r=CHECKIN")); } if(0==fileedit_is_editable(zFilename)){ fail((&err,"Filename <code>%h</code> is disallowed " "by the <code>fileedit-glob</code> repository " "setting.", zFilename)); } vid = symbolic_name_to_rid(zRev, "ci"); if(0==vid){ fail((&err,"Could not resolve checkin version.")); } cimi.zFilename = mprintf("%s",zFilename); zFileMime = mimetype_from_name(zFilename); /* Find the repo-side file entry or fail... */ cimi.zParentUuid = rid_to_uuid(vid); zFileUuid = fileedit_file_uuid(zFilename, vid, &cimi.filePerm); if(!zFileUuid){ fail((&err,"Checkin [%S] does not contain file: " "<code>%h</code>", cimi.zParentUuid, zFilename)); } else if(PERM_LNK==cimi.filePerm){ fail((&err,"Editing symlinks is not permitted.")); } frid = fast_uuid_to_rid(zFileUuid); assert(frid); /* Read file content from submit request or repo... */ if(zContent==0){ content_get(frid, &cimi.fileContent); zContent = blob_size(&cimi.fileContent) ? blob_str(&cimi.fileContent) : NULL; }else{ blob_init(&cimi.fileContent,zContent,-1); } if(looks_like_binary(&cimi.fileContent)){ fail((&err,"File appears to be binary. Cannot edit: " "<code>%h</code>",zFilename)); } /* ** TODO?: date-override date selection field. Maybe use ** an input[type=datetime-local]. */ if(SUBMIT_NONE==submitMode || P("dry_run")!=0){ cimi.flags |= CIMINI_DRY_RUN; } if(P("allow_fork")!=0){ cimi.flags |= CIMINI_ALLOW_FORK; } if(P("allow_older")!=0){ cimi.flags |= CIMINI_ALLOW_OLDER; } if(P("exec_bit")!=0){ cimi.filePerm = PERM_EXE; } if(P("allow_merge_conflict")!=0){ cimi.flags |= CIMINI_ALLOW_MERGE_MARKER; } if(P("prefer_delta")!=0){ cimi.flags |= CIMINI_PREFER_DELTA; } /* EOL conversion policy... */ { const int eolMode = submitMode==SUBMIT_NONE ? 0 : atoi(PD("eol","0")); switch(eolMode){ case 1: cimi.flags |= CIMINI_CONVERT_EOL_UNIX; break; case 2: cimi.flags |= CIMINI_CONVERT_EOL_WINDOWS; break; default: cimi.flags |= CIMINI_CONVERT_EOL_INHERIT; break; } } /******************************************************************** ** All errors which "could" have happened up to this point are of a ** degree which keep us from rendering the rest of the page, and ** thus fail() has already skipped to the end of the page to render ** the errors. Any up-coming errors, barring malloc failure or ** similar, are not "that" fatal. We can/should continue rendering ** the page, then output the error message at the end. ** ** Because we cannot intercept the output of the PREVIEW and DIFF ** rendering, we have to delay the "real work" for those modes until ** after the rest of the page has been rendered. In the case of ** SAVE, we can capture all of the output, and thus can perform that ** work before rendering, which is important so that we have the ** proper version information when rendering the rest of the page. ********************************************************************/ #undef fail while(SUBMIT_SAVE==submitMode){ Blob manifest = empty_blob; /*cimi.flags |= CIMINI_STRONGLY_PREFER_DELTA;*/ if(zComment && *zComment){ blob_append(&cimi.comment, zComment, -1); }else{ blob_append(&err,"Empty checkin comment is not permitted.",-1); break; } cimi.pMfOut = &manifest; checkin_mini(&cimi, &newVid, &err); if(newVid!=0){ char * zNewUuid = rid_to_uuid(newVid); blob_appendf(&submitResult, "<h3>Manifest%s: %S</h3><pre>" "<code class='fileedit-manifest'>%h</code>" "</pre>", (cimi.flags & CIMINI_DRY_RUN) ? " (dry run)" : "", zNewUuid, blob_str(&manifest)); if(CIMINI_DRY_RUN & cimi.flags){ fossil_free(zNewUuid); }else{ /* Update cimi version info... */ assert(cimi.pParent); assert(cimi.zParentUuid); fossil_free(zFileUuid); zFileUuid = fileedit_file_uuid(cimi.zFilename, newVid, 0); manifest_destroy(cimi.pParent); cimi.pParent = 0; fossil_free(cimi.zParentUuid); cimi.zParentUuid = zNewUuid; zComment = 0; cimi.flags |= CIMINI_DRY_RUN /* for sanity's sake */; } } /* On error, the error message is in the err blob and will ** be emitted at the end. */ cimi.pMfOut = 0; blob_reset(&manifest); break; } CX("<h1>Editing:</h1>"); CX("<p class='fileedit-hint'>"); CX("File: " "[<a id='finfo-link' href='%R/finfo?name=%T&m=%!S'>info</a>] " "<code>%h</code><br>", zFilename, zFileUuid, zFilename); CX("Checkin Version: " "[<a id='r-link' href='%R/info/%!S'>info</a>] " "<code id='r-label'>%s</code><br>", cimi.zParentUuid, cimi.zParentUuid); CX("Permalink: <code>" "<a id='permalink' href='%R/fileedit?file=%T&r=%!S'>" "/fileedit?file=%T&r=%!S</a></code><br>" "(Clicking the permalink will reload the page and discard " "all edits!)", zFilename, cimi.zParentUuid, zFilename, cimi.zParentUuid); CX("</p>"); CX("<p>This page is <em>NEW AND EXPERIMENTAL</em>. " "USE AT YOUR OWN RISK, preferably on a test " "repo.</p>\n"); CX("<form action='%R/fileedit#options' method='POST' " "class='fileedit'>\n"); /******* Hidden fields *******/ CX("<input type='hidden' name='r' value='%s'>", cimi.zParentUuid); CX("<input type='hidden' name='file' value='%T'>", zFilename); /******* Content *******/ CX("<h3>File Content</h3>\n"); CX("<textarea name='content' id='fileedit-content' " "rows='20' cols='80'>"); if(0==loadMode){ CX("%h",blob_str(&cimi.fileContent)); }else{ CX("Loading..."); /* Performed via JS later on */ } CX("</textarea>\n"); /******* Flags/options *******/ CX("<fieldset class='fileedit-options' id='options'>" "<legend>Options</legend><div>" /* Chrome does not sanely lay out multiple ** fieldset children after the <legend>, so ** a containing div is necessary. */); style_labeled_checkbox("dry_run", "Dry-run?", "1", "In dry-run mode, the Save button performs " "all work needed for saving but then rolls " "back the transaction, and thus does not " "really save.", cimi.flags & CIMINI_DRY_RUN); style_labeled_checkbox("allow_fork", "Allow fork?", "1", "Allow saving to create a fork?", cimi.flags & CIMINI_ALLOW_FORK); style_labeled_checkbox("allow_older", "Allow older?", "1", "Allow saving against a parent version " "which has a newer timestamp?", cimi.flags & CIMINI_ALLOW_OLDER); style_labeled_checkbox("exec_bit", "Executable?", "1", "Set the executable bit?", PERM_EXE==cimi.filePerm); style_labeled_checkbox("allow_merge_conflict", "Allow merge conflict markers?", "1", "Allow saving even if the content contains " "what appear to be fossil merge conflict " "markers?", cimi.flags & CIMINI_ALLOW_MERGE_MARKER); style_labeled_checkbox("prefer_delta", "Prefer delta manifest?", "1", "Will create a delta manifest, instead of " "baseline, if conditions are favorable to do " "so. This option is only a suggestion.", cimi.flags & CIMINI_PREFER_DELTA); style_select_list_int("eol", "EOL Style", "EOL conversion policy, noting that " "form-processing may implicitly change the " "line endings of the input.", (cimi.flags & CIMINI_CONVERT_EOL_UNIX) ? 1 : (cimi.flags & CIMINI_CONVERT_EOL_WINDOWS ? 2 : 0), "Inherit", 0, "Unix", 1, "Windows", 2, NULL); CX("</div></fieldset>") /* end of checkboxes */; /******* Comment *******/ CX("<a id='comment'></a>"); CX("<fieldset><legend>Commit message</legend><div>"); CX("<textarea name='comment' rows='3' cols='80'>"); /* ^^^ adding the 'required' attribute means we cannot even submit ** for PREVIEW mode if it's empty :/. */ if(zComment && *zComment){ CX("%h", zComment); } CX("</textarea>\n"); CX("<div class='fileedit-hint'>Comments use the Fossil wiki markup " "syntax.</div>\n"/*TODO: select for fossil/md/plain text*/); CX("</div></fieldset>\n"); /******* Buttons *******/ CX("<a id='buttons'></a>"); CX("<fieldset class='fileedit-options'>" "<legend>Tell the server to...</legend><div>"); CX("<button type='submit' name='submit' value='%d'>" "Commit</button>", SUBMIT_SAVE); CX("<button type='submit' name='submit' value='%d'>" "Preview</button>", SUBMIT_PREVIEW); { /* Preview rendering mode selection... */ previewRenderMode = atoi(PD("preview_render_mode","0")); if(0==previewRenderMode){ previewRenderMode = fileedit_render_mode_for_mimetype(zFileMime); } style_select_list_int("preview_render_mode", "Preview Mode", "Preview mode format.", previewRenderMode, "Guess", FE_RENDER_GUESS, "Wiki/Markdown", FE_RENDER_WIKI, "HTML (iframe)", FE_RENDER_HTML, "Plain Text", FE_RENDER_PLAIN_TEXT, NULL); if(FE_RENDER_HTML==previewRenderMode){ /* HTML preview mode iframe height... */ if(submitMode==SUBMIT_PREVIEW){ previewHtmlHeight = atoi(PD("preview_html_ems","0")); }else{ previewHtmlHeight = 40; } /* Allow selection of HTML preview iframe height */ style_select_list_int("preview_html_ems", "Preview IFrame Height (EMs)", "Height (in EMs) of the iframe used for " "HTML preview", previewHtmlHeight, "", 20, "", 40, "", 60, "", 80, "", 100, NULL); } else if(FE_RENDER_PLAIN_TEXT==previewRenderMode){ style_labeled_checkbox("preview_ln", "Add line numbers to plain-text previews?", "1", "If on, plain-text files (only) will get " "line numbers added to the preview.", previewLn); } } CX("<button type='submit' name='submit' value='%d'>" "Diff (SBS)</button>", SUBMIT_DIFF_SBS); CX("<button type='submit' name='submit' value='%d'>" "Diff (Unified)</button>", SUBMIT_DIFF_UNIFIED); CX("</div></fieldset>"); /******* End of form *******/ CX("</form>\n"); /* ** We cannot intercept the output for PREVIEW ** and DIFF modes, and therefore have to render those ** last. */ if(SUBMIT_PREVIEW==submitMode){ int pflags = 0; if(previewLn) pflags |= FE_PREVIEW_LINE_NUMBERS; fileedit_render_preview(&cimi.fileContent, cimi.zFilename, pflags, previewRenderMode, previewHtmlHeight); }else if(SUBMIT_DIFF_SBS==submitMode || SUBMIT_DIFF_UNIFIED==submitMode){ fileedit_render_diff(&cimi.fileContent, frid, cimi.zParentUuid, SUBMIT_DIFF_SBS==submitMode); } /* Dynamically populate the editor... */ fileedit_emit_script_fetch(); if(1==loadMode || (2==loadMode && submitMode>SUBMIT_NONE)){ char const * zQuoted = 0; if(blob_size(&cimi.fileContent)>0){ db_prepare(&stmt, "SELECT json_quote(%B)", &cimi.fileContent); db_step(&stmt); zQuoted = db_column_text(&stmt,0); } blob_appendf(&endScript, "/* populate editor form */\n" "document.getElementById('fileedit-content')" ".value=%s;", zQuoted ? zQuoted : "'';\n"); if(stmt.pStmt){ db_finalize(&stmt); } }else if(2==loadMode){ assert(submitMode==SUBMIT_NONE); blob_appendf(&endScript, "window.fossil.fetch('raw/%s',{" "onload: (r)=>document.getElementById('fileedit-content')" ".value=r," "onerror:()=>document.getElementById('fileedit-content')" ".value=" "'Error loading content'" "});\n", zFileUuid); } end_footer: zContent = 0; fossil_free(zFileUuid); if(stmt.pStmt){ db_finalize(&stmt); } if(blob_size(&err)){ CX("<div class='fileedit-error-report'>%s</div>", blob_str(&err)); }else if(blob_size(&submitResult)){ CX("%b",&submitResult); } blob_reset(&submitResult); blob_reset(&err); CheckinMiniInfo_cleanup(&cimi); if(blob_size(&endScript)>0){ style_emit_script_tag(0); CX("(function(){\n"); CX("try{\n%b\n}catch(e){console.error('Exception:',e)}\n", &endScript); CX("})();"); style_emit_script_tag(1); } db_end_transaction(0/*noting that dry-run mode will have already ** set this to rollback mode. */); style_footer(); } |
Changes to src/finfo.c.
︙ | ︙ | |||
619 620 621 622 623 624 625 626 627 628 629 630 631 632 | @ [annotate]</a> @ %z(href("%R/blame?filename=%h&checkin=%s",z,zCkin)) @ [blame]</a> @ %z(href("%R/timeline?n=all&uf=%!S",zUuid))[check-ins using]</a> if( fpid>0 ){ @ %z(href("%R/fdiff?v1=%!S&v2=%!S",zPUuid,zUuid))[diff]</a> } @ </span></span> } if( fDebug & FINFO_DEBUG_MLINK ){ int ii; char *zAncLink; @ <br />fid=%d(frid) pid=%d(fpid) mid=%d(fmid) if( nParent>0 ){ | > > > | 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 | @ [annotate]</a> @ %z(href("%R/blame?filename=%h&checkin=%s",z,zCkin)) @ [blame]</a> @ %z(href("%R/timeline?n=all&uf=%!S",zUuid))[check-ins using]</a> if( fpid>0 ){ @ %z(href("%R/fdiff?v1=%!S&v2=%!S",zPUuid,zUuid))[diff]</a> } if( fileedit_is_editable(zFilename) ){ @ %z(href("%R/fileedit?file=%T&r=%!S",zFilename,zCkin))[edit]</a> } @ </span></span> } if( fDebug & FINFO_DEBUG_MLINK ){ int ii; char *zAncLink; @ <br />fid=%d(frid) pid=%d(fpid) mid=%d(fmid) if( nParent>0 ){ |
︙ | ︙ |
Changes to src/info.c.
︙ | ︙ | |||
1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 | @ size: %d(szFile)) if( g.perm.Hyperlink ){ @ %z(href("%R/annotate?filename=%T&checkin=%!S",zName,zVers)) @ [annotate]</a> @ %z(href("%R/blame?filename=%T&checkin=%!S",zName,zVers)) @ [blame]</a> @ %z(href("%R/timeline?n=all&uf=%!S",zUuid))[check-ins using]</a> } cnt++; if( pDownloadName && blob_size(pDownloadName)==0 ){ blob_append(pDownloadName, zName, -1); } } if( prevName && showDetail ){ | > > > | 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 | @ size: %d(szFile)) if( g.perm.Hyperlink ){ @ %z(href("%R/annotate?filename=%T&checkin=%!S",zName,zVers)) @ [annotate]</a> @ %z(href("%R/blame?filename=%T&checkin=%!S",zName,zVers)) @ [blame]</a> @ %z(href("%R/timeline?n=all&uf=%!S",zUuid))[check-ins using]</a> if( fileedit_is_editable(zName) ){ @ %z(href("%R/fileedit?file=%T&r=%!S",zName,zVers))[edit]</a> } } cnt++; if( pDownloadName && blob_size(pDownloadName)==0 ){ blob_append(pDownloadName, zName, -1); } } if( prevName && showDetail ){ |
︙ | ︙ |
Changes to src/leaf.c.
︙ | ︙ | |||
150 151 152 153 154 155 156 157 158 159 160 161 162 163 | "EXISTS(SELECT 1 FROM tagxref AS tx" " WHERE tx.rid=%s" " AND tx.tagid=%d" " AND tx.tagtype>0)", zVar, TAG_CLOSED ); } /* ** Schedule a leaf check for "rid" and its parents. */ void leaf_eventually_check(int rid){ static Stmt parentsOf; | > > > > > > > > > > > | 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 | "EXISTS(SELECT 1 FROM tagxref AS tx" " WHERE tx.rid=%s" " AND tx.tagid=%d" " AND tx.tagtype>0)", zVar, TAG_CLOSED ); } /* ** Returns true if vid refers to a closed leaf, else false. vid is ** assumed to refer to a manifest, but this function does not verify ** that. */ int leaf_is_closed(int vid){ return db_exists("SELECT 1 FROM tagxref" " WHERE tagid=%d AND rid=%d AND tagtype>0", TAG_CLOSED, vid); } /* ** Schedule a leaf check for "rid" and its parents. */ void leaf_eventually_check(int rid){ static Stmt parentsOf; |
︙ | ︙ |
Changes to src/main.c.
︙ | ︙ | |||
2810 2811 2812 2813 2814 2815 2816 | } } } #else zBrowser = db_get("web-browser", "open"); #endif if( zIpAddr==0 ){ | | | | | 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 | } } } #else zBrowser = db_get("web-browser", "open"); #endif if( zIpAddr==0 ){ zBrowserCmd = mprintf("%s \"http://localhost:%%d/%s\" &", zBrowser, zInitPage); }else if( strchr(zIpAddr,':') ){ zBrowserCmd = mprintf("%s \"http://[%s]:%%d/%s\" &", zBrowser, zIpAddr, zInitPage); }else{ zBrowserCmd = mprintf("%s \"http://%s:%%d/%s\" &", zBrowser, zIpAddr, zInitPage); } } if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY; if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT; db_close(1); if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){ |
︙ | ︙ |
Changes to src/main.mk.
︙ | ︙ | |||
52 53 54 55 56 57 58 59 60 61 62 63 64 65 | $(SRCDIR)/doc.c \ $(SRCDIR)/encode.c \ $(SRCDIR)/etag.c \ $(SRCDIR)/event.c \ $(SRCDIR)/export.c \ $(SRCDIR)/extcgi.c \ $(SRCDIR)/file.c \ $(SRCDIR)/finfo.c \ $(SRCDIR)/foci.c \ $(SRCDIR)/forum.c \ $(SRCDIR)/fshell.c \ $(SRCDIR)/fusefs.c \ $(SRCDIR)/fuzz.c \ $(SRCDIR)/glob.c \ | > | 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | $(SRCDIR)/doc.c \ $(SRCDIR)/encode.c \ $(SRCDIR)/etag.c \ $(SRCDIR)/event.c \ $(SRCDIR)/export.c \ $(SRCDIR)/extcgi.c \ $(SRCDIR)/file.c \ $(SRCDIR)/fileedit.c \ $(SRCDIR)/finfo.c \ $(SRCDIR)/foci.c \ $(SRCDIR)/forum.c \ $(SRCDIR)/fshell.c \ $(SRCDIR)/fusefs.c \ $(SRCDIR)/fuzz.c \ $(SRCDIR)/glob.c \ |
︙ | ︙ | |||
285 286 287 288 289 290 291 292 293 294 295 296 297 298 | $(OBJDIR)/doc_.c \ $(OBJDIR)/encode_.c \ $(OBJDIR)/etag_.c \ $(OBJDIR)/event_.c \ $(OBJDIR)/export_.c \ $(OBJDIR)/extcgi_.c \ $(OBJDIR)/file_.c \ $(OBJDIR)/finfo_.c \ $(OBJDIR)/foci_.c \ $(OBJDIR)/forum_.c \ $(OBJDIR)/fshell_.c \ $(OBJDIR)/fusefs_.c \ $(OBJDIR)/fuzz_.c \ $(OBJDIR)/glob_.c \ | > | 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 | $(OBJDIR)/doc_.c \ $(OBJDIR)/encode_.c \ $(OBJDIR)/etag_.c \ $(OBJDIR)/event_.c \ $(OBJDIR)/export_.c \ $(OBJDIR)/extcgi_.c \ $(OBJDIR)/file_.c \ $(OBJDIR)/fileedit_.c \ $(OBJDIR)/finfo_.c \ $(OBJDIR)/foci_.c \ $(OBJDIR)/forum_.c \ $(OBJDIR)/fshell_.c \ $(OBJDIR)/fusefs_.c \ $(OBJDIR)/fuzz_.c \ $(OBJDIR)/glob_.c \ |
︙ | ︙ | |||
427 428 429 430 431 432 433 434 435 436 437 438 439 440 | $(OBJDIR)/doc.o \ $(OBJDIR)/encode.o \ $(OBJDIR)/etag.o \ $(OBJDIR)/event.o \ $(OBJDIR)/export.o \ $(OBJDIR)/extcgi.o \ $(OBJDIR)/file.o \ $(OBJDIR)/finfo.o \ $(OBJDIR)/foci.o \ $(OBJDIR)/forum.o \ $(OBJDIR)/fshell.o \ $(OBJDIR)/fusefs.o \ $(OBJDIR)/fuzz.o \ $(OBJDIR)/glob.o \ | > | 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 | $(OBJDIR)/doc.o \ $(OBJDIR)/encode.o \ $(OBJDIR)/etag.o \ $(OBJDIR)/event.o \ $(OBJDIR)/export.o \ $(OBJDIR)/extcgi.o \ $(OBJDIR)/file.o \ $(OBJDIR)/fileedit.o \ $(OBJDIR)/finfo.o \ $(OBJDIR)/foci.o \ $(OBJDIR)/forum.o \ $(OBJDIR)/fshell.o \ $(OBJDIR)/fusefs.o \ $(OBJDIR)/fuzz.o \ $(OBJDIR)/glob.o \ |
︙ | ︙ | |||
764 765 766 767 768 769 770 771 772 773 774 775 776 777 | $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h \ $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \ $(OBJDIR)/etag_.c:$(OBJDIR)/etag.h \ $(OBJDIR)/event_.c:$(OBJDIR)/event.h \ $(OBJDIR)/export_.c:$(OBJDIR)/export.h \ $(OBJDIR)/extcgi_.c:$(OBJDIR)/extcgi.h \ $(OBJDIR)/file_.c:$(OBJDIR)/file.h \ $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h \ $(OBJDIR)/foci_.c:$(OBJDIR)/foci.h \ $(OBJDIR)/forum_.c:$(OBJDIR)/forum.h \ $(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \ $(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \ $(OBJDIR)/fuzz_.c:$(OBJDIR)/fuzz.h \ $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \ | > | 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 | $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h \ $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \ $(OBJDIR)/etag_.c:$(OBJDIR)/etag.h \ $(OBJDIR)/event_.c:$(OBJDIR)/event.h \ $(OBJDIR)/export_.c:$(OBJDIR)/export.h \ $(OBJDIR)/extcgi_.c:$(OBJDIR)/extcgi.h \ $(OBJDIR)/file_.c:$(OBJDIR)/file.h \ $(OBJDIR)/fileedit_.c:$(OBJDIR)/fileedit.h \ $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h \ $(OBJDIR)/foci_.c:$(OBJDIR)/foci.h \ $(OBJDIR)/forum_.c:$(OBJDIR)/forum.h \ $(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \ $(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \ $(OBJDIR)/fuzz_.c:$(OBJDIR)/fuzz.h \ $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \ |
︙ | ︙ | |||
1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 | $(OBJDIR)/file_.c: $(SRCDIR)/file.c $(OBJDIR)/translate $(OBJDIR)/translate $(SRCDIR)/file.c >$@ $(OBJDIR)/file.o: $(OBJDIR)/file_.c $(OBJDIR)/file.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/file.o -c $(OBJDIR)/file_.c $(OBJDIR)/file.h: $(OBJDIR)/headers $(OBJDIR)/finfo_.c: $(SRCDIR)/finfo.c $(OBJDIR)/translate $(OBJDIR)/translate $(SRCDIR)/finfo.c >$@ $(OBJDIR)/finfo.o: $(OBJDIR)/finfo_.c $(OBJDIR)/finfo.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/finfo.o -c $(OBJDIR)/finfo_.c | > > > > > > > > | 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 | $(OBJDIR)/file_.c: $(SRCDIR)/file.c $(OBJDIR)/translate $(OBJDIR)/translate $(SRCDIR)/file.c >$@ $(OBJDIR)/file.o: $(OBJDIR)/file_.c $(OBJDIR)/file.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/file.o -c $(OBJDIR)/file_.c $(OBJDIR)/file.h: $(OBJDIR)/headers $(OBJDIR)/fileedit_.c: $(SRCDIR)/fileedit.c $(OBJDIR)/translate $(OBJDIR)/translate $(SRCDIR)/fileedit.c >$@ $(OBJDIR)/fileedit.o: $(OBJDIR)/fileedit_.c $(OBJDIR)/fileedit.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/fileedit.o -c $(OBJDIR)/fileedit_.c $(OBJDIR)/fileedit.h: $(OBJDIR)/headers $(OBJDIR)/finfo_.c: $(SRCDIR)/finfo.c $(OBJDIR)/translate $(OBJDIR)/translate $(SRCDIR)/finfo.c >$@ $(OBJDIR)/finfo.o: $(OBJDIR)/finfo_.c $(OBJDIR)/finfo.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/finfo.o -c $(OBJDIR)/finfo_.c |
︙ | ︙ |
Changes to src/makemake.tcl.
︙ | ︙ | |||
63 64 65 66 67 68 69 70 71 72 73 74 75 76 | doc encode etag event extcgi export file finfo foci forum fshell fusefs fuzz glob | > | 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | doc encode etag event extcgi export file fileedit finfo foci forum fshell fusefs fuzz glob |
︙ | ︙ |
Changes to src/manifest.c.
︙ | ︙ | |||
1062 1063 1064 1065 1066 1067 1068 | md5sum_init(); if( !isRepeat ) g.parseCnt[p->type]++; return p; manifest_syntax_error: { | | | 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 | md5sum_init(); if( !isRepeat ) g.parseCnt[p->type]++; return p; manifest_syntax_error: { char *zUuid = rid_to_uuid(rid); if( zUuid ){ blob_appendf(pErr, "artifact [%s] ", zUuid); fossil_free(zUuid); } } if( zErr ){ blob_appendf(pErr, "line %d: %s", lineNo, zErr); |
︙ | ︙ | |||
1325 1326 1327 1328 1329 1330 1331 | return fnid; } /* ** Compute an appropriate mlink.mperm integer for the permission string ** of a file. */ | | | 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 | return fnid; } /* ** Compute an appropriate mlink.mperm integer for the permission string ** of a file. */ int manifest_file_mperm(const ManifestFile *pFile){ int mperm = PERM_REG; if( pFile && pFile->zPerm){ if( strstr(pFile->zPerm,"x")!=0 ){ mperm = PERM_EXE; }else if( strstr(pFile->zPerm,"l")!=0 ){ mperm = PERM_LNK; } |
︙ | ︙ |
Changes to src/style.c.
︙ | ︙ | |||
1293 1294 1295 1296 1297 1298 1299 | cgi_reset_content(); webpage_error("assertion fault at %s:%d - %s", zFile, iLine, zExpr); } #if INTERFACE # define webpage_assert(T) if(!(T)){webpage_assert_page(__FILE__,__LINE__,#T);} #endif | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 | cgi_reset_content(); webpage_error("assertion fault at %s:%d - %s", zFile, iLine, zExpr); } #if INTERFACE # define webpage_assert(T) if(!(T)){webpage_assert_page(__FILE__,__LINE__,#T);} #endif /* ** Outputs a labeled checkbox element. zFieldName is the form element ** name. zLabel is the label for the checkbox. zValue is the optional ** value for the checkbox. zTip is an optional tooltip, which gets set ** as the "title" attribute of the outermost element. If isChecked is ** true, the checkbox gets the "checked" attribute set, else it is ** not. ** ** Resulting structure: ** ** <div class='input-with-label' title={{zTip}}> ** <input type='checkbox' name={{zFieldName}} value={{zValue}} ** {{isChecked ? " checked : ""}}/> ** <span>{{zLabel}}</span> ** </div> ** ** zFieldName, zLabel, and zValue are required. zTip is optional. ** ** Be sure that the input-with-label CSS class is defined sensibly, in ** particular, having its display:inline-block is useful for alignment ** purposes. */ void style_labeled_checkbox(const char *zFieldName, const char * zLabel, const char * zValue, const char * zTip, int isChecked){ CX("<div class='input-with-label'"); if(zTip && *zTip){ CX(" title='%h'", zTip); } CX("><input type='checkbox' name='%s' value='%T'%s/>", zFieldName, zValue ? zValue : "", isChecked ? " checked" : ""); CX("<span>%h</span></div>", zLabel); } /* ** Outputs a SELECT list from a compile-time list of integers. ** The vargs must be a list of (const char *, int) pairs, terminated ** with a single NULL. Each pair is interpreted as... ** ** If the (const char *) is NULL, it is the end of the list, else ** a new OPTION entry is created. If the string is empty, the ** label and value of the OPTION is the integer part of the pair. ** If the string is not empty, it becomes the label and the integer ** the value. If that value == selectedValue then that OPTION ** element gets the 'selected' attribute. ** ** Note that the pairs are not in (int, const char *) order because ** there is no well-known integer value which we can definitively use ** as a list terminator. ** ** zFieldName is the value of the form element's name attribute. ** ** zLabel is an optional string to use as a "label" for the element ** (see below). ** ** zTooltip is an optional value for the SELECT's title attribute. ** ** The structure of the emitted HTML is: ** ** <div class='input-with-label' title={{zToolTip}}> ** <span>{{zLabel}}</span> ** <select>...</select> ** </div> ** ** Example: ** ** style_select_list_int("my_field", "Grapes", ** "Select the number of grapes", ** atoi(PD("my_field","0")), ** "", 1, "2", 2, "Three", 3, ** NULL); ** */ void style_select_list_int(const char *zFieldName, const char * zLabel, const char * zToolTip, int selectedVal, ... ){ va_list vargs; va_start(vargs,selectedVal); CX("<div class='input-with-label'"); if(zToolTip && *zToolTip){ CX(" title='%h'",zToolTip); } CX(">"); if(zLabel && *zLabel){ CX("<span>%h</span>", zLabel); } CX("<select name='%s'>",zFieldName); while(1){ const char * zOption = va_arg(vargs,char *); int v; if(NULL==zOption){ break; } v = va_arg(vargs,int); CX("<option value='%d'%s>", v, v==selectedVal ? " selected" : ""); if(*zOption){ CX("%s", zOption); }else{ CX("%d",v); } CX("</option>\n"); } CX("</select>\n"); if(zLabel && *zLabel){ CX("</div>\n"); } va_end(vargs); } /* ** If passed 0, it emits a script opener tag with this session's ** nonce. If passed non-0 it emits a script closing tag. The very ** first time it is called, it emits some bootstrapping JS code ** immediately after the script opener. Specifically, it defines ** window.fossil if it's not already defined, and may set some ** properties on it. */ void style_emit_script_tag(int phase){ static int once = 0; if(0==phase){ CX("<script nonce='%s'>", style_nonce()); if(0==once){ once = 1; CX("\nif(!window.fossil) window.fossil={};\n"); CX("window.fossil.version = %Q;\n", get_version()); } }else{ CX("</script>\n"); } } |
Changes to win/Makefile.dmc.
︙ | ︙ | |||
26 27 28 29 30 31 32 | TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL) LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32 dnsapi SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_GET_TABLE -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 SHELL_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_GET_TABLE -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen | | | | | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL) LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32 dnsapi SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_GET_TABLE -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 SHELL_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_GET_TABLE -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen SRC = add_.c alerts_.c allrepo_.c attach_.c backlink_.c backoffice_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c capabilities_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c cookies_.c db_.c delta_.c deltacmd_.c deltafunc_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c etag_.c event_.c export_.c extcgi_.c file_.c fileedit_.c finfo_.c foci_.c forum_.c fshell_.c fusefs_.c fuzz_.c glob_.c graph_.c gzip_.c hname_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c piechart_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c repolist_.c report_.c rss_.c schema_.c search_.c security_audit_.c setup_.c setupuser_.c sha1_.c sha1hard_.c sha3_.c shun_.c sitemap_.c skins_.c smtp_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c unversioned_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c webmail_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c OBJ = $(OBJDIR)\add$O $(OBJDIR)\alerts$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\backlink$O $(OBJDIR)\backoffice$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\builtin$O $(OBJDIR)\bundle$O $(OBJDIR)\cache$O $(OBJDIR)\capabilities$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\cookies$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\deltafunc$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\dispatch$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\etag$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\extcgi$O $(OBJDIR)\file$O $(OBJDIR)\fileedit$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\forum$O $(OBJDIR)\fshell$O $(OBJDIR)\fusefs$O $(OBJDIR)\fuzz$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\hname$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\piechart$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\publish$O $(OBJDIR)\purge$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\repolist$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\security_audit$O $(OBJDIR)\setup$O $(OBJDIR)\setupuser$O $(OBJDIR)\sha1$O $(OBJDIR)\sha1hard$O $(OBJDIR)\sha3$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\smtp$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\statrep$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\unversioned$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\webmail$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O RC=$(DMDIR)\bin\rcc RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__ APPNAME = $(OBJDIR)\fossil$(E) all: $(APPNAME) $(APPNAME) : translate$E mkindex$E codecheck1$E headers $(OBJ) $(OBJDIR)\link cd $(OBJDIR) codecheck1$E $(SRC) $(DMDIR)\bin\link @link $(OBJDIR)\fossil.res: $B\win\fossil.rc $(RC) $(RCFLAGS) -o$@ $** $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res +echo add alerts allrepo attach backlink backoffice bag bisect blob branch browse builtin bundle cache capabilities captcha cgi checkin checkout clearsign clone comformat configure content cookies db delta deltacmd deltafunc descendants diff diffcmd dispatch doc encode etag event export extcgi file fileedit finfo foci forum fshell fusefs fuzz glob graph gzip hname http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf loadctrl login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name path piechart pivot popen pqueue printf publish purge rebuild regexp repolist report rss schema search security_audit setup setupuser sha1 sha1hard sha3 shun sitemap skins smtp sqlcmd stash stat statrep style sync tag tar th_main timeline tkt tktsetup undo unicode unversioned update url user utf8 util verify vfile webmail wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@ +echo fossil >> $@ +echo fossil >> $@ +echo $(LIBS) >> $@ +echo. >> $@ +echo fossil >> $@ translate$E: $(SRCDIR)\translate.c |
︙ | ︙ | |||
366 367 368 369 370 371 372 373 374 375 376 377 378 379 | +translate$E $** > $@ $(OBJDIR)\file$O : file_.c file.h $(TCC) -o$@ -c file_.c file_.c : $(SRCDIR)\file.c +translate$E $** > $@ $(OBJDIR)\finfo$O : finfo_.c finfo.h $(TCC) -o$@ -c finfo_.c finfo_.c : $(SRCDIR)\finfo.c +translate$E $** > $@ | > > > > > > | 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 | +translate$E $** > $@ $(OBJDIR)\file$O : file_.c file.h $(TCC) -o$@ -c file_.c file_.c : $(SRCDIR)\file.c +translate$E $** > $@ $(OBJDIR)\fileedit$O : fileedit_.c fileedit.h $(TCC) -o$@ -c fileedit_.c fileedit_.c : $(SRCDIR)\fileedit.c +translate$E $** > $@ $(OBJDIR)\finfo$O : finfo_.c finfo.h $(TCC) -o$@ -c finfo_.c finfo_.c : $(SRCDIR)\finfo.c +translate$E $** > $@ |
︙ | ︙ | |||
968 969 970 971 972 973 974 | $(OBJDIR)\zip$O : zip_.c zip.h $(TCC) -o$@ -c zip_.c zip_.c : $(SRCDIR)\zip.c +translate$E $** > $@ headers: makeheaders$E page_index.h builtin_data.h default_css.h VERSION.h | | | 974 975 976 977 978 979 980 981 982 | $(OBJDIR)\zip$O : zip_.c zip.h $(TCC) -o$@ -c zip_.c zip_.c : $(SRCDIR)\zip.c +translate$E $** > $@ headers: makeheaders$E page_index.h builtin_data.h default_css.h VERSION.h +makeheaders$E add_.c:add.h alerts_.c:alerts.h allrepo_.c:allrepo.h attach_.c:attach.h backlink_.c:backlink.h backoffice_.c:backoffice.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h builtin_.c:builtin.h bundle_.c:bundle.h cache_.c:cache.h capabilities_.c:capabilities.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h cookies_.c:cookies.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h deltafunc_.c:deltafunc.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h dispatch_.c:dispatch.h doc_.c:doc.h encode_.c:encode.h etag_.c:etag.h event_.c:event.h export_.c:export.h extcgi_.c:extcgi.h file_.c:file.h fileedit_.c:fileedit.h finfo_.c:finfo.h foci_.c:foci.h forum_.c:forum.h fshell_.c:fshell.h fusefs_.c:fusefs.h fuzz_.c:fuzz.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h hname_.c:hname.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h loadctrl_.c:loadctrl.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h piechart_.c:piechart.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h publish_.c:publish.h purge_.c:purge.h rebuild_.c:rebuild.h regexp_.c:regexp.h repolist_.c:repolist.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h security_audit_.c:security_audit.h setup_.c:setup.h setupuser_.c:setupuser.h sha1_.c:sha1.h sha1hard_.c:sha1hard.h sha3_.c:sha3.h shun_.c:shun.h sitemap_.c:sitemap.h skins_.c:skins.h smtp_.c:smtp.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h statrep_.c:statrep.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h unversioned_.c:unversioned.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h webmail_.c:webmail.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h @copy /Y nul: headers |
Changes to win/Makefile.mingw.
︙ | ︙ | |||
474 475 476 477 478 479 480 481 482 483 484 485 486 487 | $(SRCDIR)/doc.c \ $(SRCDIR)/encode.c \ $(SRCDIR)/etag.c \ $(SRCDIR)/event.c \ $(SRCDIR)/export.c \ $(SRCDIR)/extcgi.c \ $(SRCDIR)/file.c \ $(SRCDIR)/finfo.c \ $(SRCDIR)/foci.c \ $(SRCDIR)/forum.c \ $(SRCDIR)/fshell.c \ $(SRCDIR)/fusefs.c \ $(SRCDIR)/fuzz.c \ $(SRCDIR)/glob.c \ | > | 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 | $(SRCDIR)/doc.c \ $(SRCDIR)/encode.c \ $(SRCDIR)/etag.c \ $(SRCDIR)/event.c \ $(SRCDIR)/export.c \ $(SRCDIR)/extcgi.c \ $(SRCDIR)/file.c \ $(SRCDIR)/fileedit.c \ $(SRCDIR)/finfo.c \ $(SRCDIR)/foci.c \ $(SRCDIR)/forum.c \ $(SRCDIR)/fshell.c \ $(SRCDIR)/fusefs.c \ $(SRCDIR)/fuzz.c \ $(SRCDIR)/glob.c \ |
︙ | ︙ | |||
707 708 709 710 711 712 713 714 715 716 717 718 719 720 | $(OBJDIR)/doc_.c \ $(OBJDIR)/encode_.c \ $(OBJDIR)/etag_.c \ $(OBJDIR)/event_.c \ $(OBJDIR)/export_.c \ $(OBJDIR)/extcgi_.c \ $(OBJDIR)/file_.c \ $(OBJDIR)/finfo_.c \ $(OBJDIR)/foci_.c \ $(OBJDIR)/forum_.c \ $(OBJDIR)/fshell_.c \ $(OBJDIR)/fusefs_.c \ $(OBJDIR)/fuzz_.c \ $(OBJDIR)/glob_.c \ | > | 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 | $(OBJDIR)/doc_.c \ $(OBJDIR)/encode_.c \ $(OBJDIR)/etag_.c \ $(OBJDIR)/event_.c \ $(OBJDIR)/export_.c \ $(OBJDIR)/extcgi_.c \ $(OBJDIR)/file_.c \ $(OBJDIR)/fileedit_.c \ $(OBJDIR)/finfo_.c \ $(OBJDIR)/foci_.c \ $(OBJDIR)/forum_.c \ $(OBJDIR)/fshell_.c \ $(OBJDIR)/fusefs_.c \ $(OBJDIR)/fuzz_.c \ $(OBJDIR)/glob_.c \ |
︙ | ︙ | |||
849 850 851 852 853 854 855 856 857 858 859 860 861 862 | $(OBJDIR)/doc.o \ $(OBJDIR)/encode.o \ $(OBJDIR)/etag.o \ $(OBJDIR)/event.o \ $(OBJDIR)/export.o \ $(OBJDIR)/extcgi.o \ $(OBJDIR)/file.o \ $(OBJDIR)/finfo.o \ $(OBJDIR)/foci.o \ $(OBJDIR)/forum.o \ $(OBJDIR)/fshell.o \ $(OBJDIR)/fusefs.o \ $(OBJDIR)/fuzz.o \ $(OBJDIR)/glob.o \ | > | 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 | $(OBJDIR)/doc.o \ $(OBJDIR)/encode.o \ $(OBJDIR)/etag.o \ $(OBJDIR)/event.o \ $(OBJDIR)/export.o \ $(OBJDIR)/extcgi.o \ $(OBJDIR)/file.o \ $(OBJDIR)/fileedit.o \ $(OBJDIR)/finfo.o \ $(OBJDIR)/foci.o \ $(OBJDIR)/forum.o \ $(OBJDIR)/fshell.o \ $(OBJDIR)/fusefs.o \ $(OBJDIR)/fuzz.o \ $(OBJDIR)/glob.o \ |
︙ | ︙ | |||
1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 | $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h \ $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \ $(OBJDIR)/etag_.c:$(OBJDIR)/etag.h \ $(OBJDIR)/event_.c:$(OBJDIR)/event.h \ $(OBJDIR)/export_.c:$(OBJDIR)/export.h \ $(OBJDIR)/extcgi_.c:$(OBJDIR)/extcgi.h \ $(OBJDIR)/file_.c:$(OBJDIR)/file.h \ $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h \ $(OBJDIR)/foci_.c:$(OBJDIR)/foci.h \ $(OBJDIR)/forum_.c:$(OBJDIR)/forum.h \ $(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \ $(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \ $(OBJDIR)/fuzz_.c:$(OBJDIR)/fuzz.h \ $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \ | > | 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 | $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h \ $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \ $(OBJDIR)/etag_.c:$(OBJDIR)/etag.h \ $(OBJDIR)/event_.c:$(OBJDIR)/event.h \ $(OBJDIR)/export_.c:$(OBJDIR)/export.h \ $(OBJDIR)/extcgi_.c:$(OBJDIR)/extcgi.h \ $(OBJDIR)/file_.c:$(OBJDIR)/file.h \ $(OBJDIR)/fileedit_.c:$(OBJDIR)/fileedit.h \ $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h \ $(OBJDIR)/foci_.c:$(OBJDIR)/foci.h \ $(OBJDIR)/forum_.c:$(OBJDIR)/forum.h \ $(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \ $(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \ $(OBJDIR)/fuzz_.c:$(OBJDIR)/fuzz.h \ $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \ |
︙ | ︙ | |||
1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 | $(OBJDIR)/file_.c: $(SRCDIR)/file.c $(TRANSLATE) $(TRANSLATE) $(SRCDIR)/file.c >$@ $(OBJDIR)/file.o: $(OBJDIR)/file_.c $(OBJDIR)/file.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/file.o -c $(OBJDIR)/file_.c $(OBJDIR)/file.h: $(OBJDIR)/headers $(OBJDIR)/finfo_.c: $(SRCDIR)/finfo.c $(TRANSLATE) $(TRANSLATE) $(SRCDIR)/finfo.c >$@ $(OBJDIR)/finfo.o: $(OBJDIR)/finfo_.c $(OBJDIR)/finfo.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/finfo.o -c $(OBJDIR)/finfo_.c | > > > > > > > > | 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 | $(OBJDIR)/file_.c: $(SRCDIR)/file.c $(TRANSLATE) $(TRANSLATE) $(SRCDIR)/file.c >$@ $(OBJDIR)/file.o: $(OBJDIR)/file_.c $(OBJDIR)/file.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/file.o -c $(OBJDIR)/file_.c $(OBJDIR)/file.h: $(OBJDIR)/headers $(OBJDIR)/fileedit_.c: $(SRCDIR)/fileedit.c $(TRANSLATE) $(TRANSLATE) $(SRCDIR)/fileedit.c >$@ $(OBJDIR)/fileedit.o: $(OBJDIR)/fileedit_.c $(OBJDIR)/fileedit.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/fileedit.o -c $(OBJDIR)/fileedit_.c $(OBJDIR)/fileedit.h: $(OBJDIR)/headers $(OBJDIR)/finfo_.c: $(SRCDIR)/finfo.c $(TRANSLATE) $(TRANSLATE) $(SRCDIR)/finfo.c >$@ $(OBJDIR)/finfo.o: $(OBJDIR)/finfo_.c $(OBJDIR)/finfo.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/finfo.o -c $(OBJDIR)/finfo_.c |
︙ | ︙ |
Changes to win/Makefile.msc.
︙ | ︙ | |||
382 383 384 385 386 387 388 389 390 391 392 393 394 395 | doc_.c \ encode_.c \ etag_.c \ event_.c \ export_.c \ extcgi_.c \ file_.c \ finfo_.c \ foci_.c \ forum_.c \ fshell_.c \ fusefs_.c \ fuzz_.c \ glob_.c \ | > | 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 | doc_.c \ encode_.c \ etag_.c \ event_.c \ export_.c \ extcgi_.c \ file_.c \ fileedit_.c \ finfo_.c \ foci_.c \ forum_.c \ fshell_.c \ fusefs_.c \ fuzz_.c \ glob_.c \ |
︙ | ︙ | |||
614 615 616 617 618 619 620 621 622 623 624 625 626 627 | $(OX)\doc$O \ $(OX)\encode$O \ $(OX)\etag$O \ $(OX)\event$O \ $(OX)\export$O \ $(OX)\extcgi$O \ $(OX)\file$O \ $(OX)\finfo$O \ $(OX)\foci$O \ $(OX)\forum$O \ $(OX)\fshell$O \ $(OX)\fusefs$O \ $(OX)\fuzz$O \ $(OX)\glob$O \ | > | 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 | $(OX)\doc$O \ $(OX)\encode$O \ $(OX)\etag$O \ $(OX)\event$O \ $(OX)\export$O \ $(OX)\extcgi$O \ $(OX)\file$O \ $(OX)\fileedit$O \ $(OX)\finfo$O \ $(OX)\foci$O \ $(OX)\forum$O \ $(OX)\fshell$O \ $(OX)\fusefs$O \ $(OX)\fuzz$O \ $(OX)\glob$O \ |
︙ | ︙ | |||
818 819 820 821 822 823 824 825 826 827 828 829 830 831 | echo $(OX)\doc.obj >> $@ echo $(OX)\encode.obj >> $@ echo $(OX)\etag.obj >> $@ echo $(OX)\event.obj >> $@ echo $(OX)\export.obj >> $@ echo $(OX)\extcgi.obj >> $@ echo $(OX)\file.obj >> $@ echo $(OX)\finfo.obj >> $@ echo $(OX)\foci.obj >> $@ echo $(OX)\forum.obj >> $@ echo $(OX)\fshell.obj >> $@ echo $(OX)\fusefs.obj >> $@ echo $(OX)\fuzz.obj >> $@ echo $(OX)\glob.obj >> $@ | > | 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 | echo $(OX)\doc.obj >> $@ echo $(OX)\encode.obj >> $@ echo $(OX)\etag.obj >> $@ echo $(OX)\event.obj >> $@ echo $(OX)\export.obj >> $@ echo $(OX)\extcgi.obj >> $@ echo $(OX)\file.obj >> $@ echo $(OX)\fileedit.obj >> $@ echo $(OX)\finfo.obj >> $@ echo $(OX)\foci.obj >> $@ echo $(OX)\forum.obj >> $@ echo $(OX)\fshell.obj >> $@ echo $(OX)\fusefs.obj >> $@ echo $(OX)\fuzz.obj >> $@ echo $(OX)\glob.obj >> $@ |
︙ | ︙ | |||
1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 | translate$E $** > $@ $(OX)\file$O : file_.c file.h $(TCC) /Fo$@ -c file_.c file_.c : $(SRCDIR)\file.c translate$E $** > $@ $(OX)\finfo$O : finfo_.c finfo.h $(TCC) /Fo$@ -c finfo_.c finfo_.c : $(SRCDIR)\finfo.c translate$E $** > $@ | > > > > > > | 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 | translate$E $** > $@ $(OX)\file$O : file_.c file.h $(TCC) /Fo$@ -c file_.c file_.c : $(SRCDIR)\file.c translate$E $** > $@ $(OX)\fileedit$O : fileedit_.c fileedit.h $(TCC) /Fo$@ -c fileedit_.c fileedit_.c : $(SRCDIR)\fileedit.c translate$E $** > $@ $(OX)\finfo$O : finfo_.c finfo.h $(TCC) /Fo$@ -c finfo_.c finfo_.c : $(SRCDIR)\finfo.c translate$E $** > $@ |
︙ | ︙ | |||
1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 | doc_.c:doc.h \ encode_.c:encode.h \ etag_.c:etag.h \ event_.c:event.h \ export_.c:export.h \ extcgi_.c:extcgi.h \ file_.c:file.h \ finfo_.c:finfo.h \ foci_.c:foci.h \ forum_.c:forum.h \ fshell_.c:fshell.h \ fusefs_.c:fusefs.h \ fuzz_.c:fuzz.h \ glob_.c:glob.h \ | > | 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 | doc_.c:doc.h \ encode_.c:encode.h \ etag_.c:etag.h \ event_.c:event.h \ export_.c:export.h \ extcgi_.c:extcgi.h \ file_.c:file.h \ fileedit_.c:fileedit.h \ finfo_.c:finfo.h \ foci_.c:foci.h \ forum_.c:forum.h \ fshell_.c:fshell.h \ fusefs_.c:fusefs.h \ fuzz_.c:fuzz.h \ glob_.c:glob.h \ |
︙ | ︙ |