Fossil SCM
Add support for the --undo option to the "fossil diff" command.
Commit
485aa80625acdb31f612b4c30a4a810e6d1fad45
Parent
4140eb35757eea1…
1 file changed
+97
-21
+97
-21
| --- src/diffcmd.c | ||
| +++ src/diffcmd.c | ||
| @@ -276,11 +276,11 @@ | ||
| 276 | 276 | blob_reset(&cmd); |
| 277 | 277 | } |
| 278 | 278 | } |
| 279 | 279 | |
| 280 | 280 | /* |
| 281 | -** Do a diff against a single file named in zFileTreeName from version zFrom | |
| 281 | +** Do a diff against a single file named in zFile from version zFrom | |
| 282 | 282 | ** against the same file on disk. |
| 283 | 283 | ** |
| 284 | 284 | ** Use the internal diff logic if zDiffCmd is NULL. Otherwise call the |
| 285 | 285 | ** command zDiffCmd to do the diffing. |
| 286 | 286 | ** |
| @@ -292,23 +292,23 @@ | ||
| 292 | 292 | const char *zFrom, /* Version tag for the "before" file */ |
| 293 | 293 | const char *zDiffCmd, /* Use this "diff" command */ |
| 294 | 294 | const char *zBinGlob, /* Treat file names matching this as binary */ |
| 295 | 295 | int fIncludeBinary, /* Include binary files for external diff */ |
| 296 | 296 | u64 diffFlags, /* Diff control flags */ |
| 297 | - const char *zFileTreeName /* Name of the file to be diffed */ | |
| 297 | + const char *zFile /* Name of the file to be diffed */ | |
| 298 | 298 | ){ |
| 299 | 299 | Blob fname; |
| 300 | 300 | Blob content; |
| 301 | 301 | int isLink; |
| 302 | 302 | int isBin; |
| 303 | - file_tree_name(zFileTreeName, &fname, 0, 1); | |
| 303 | + file_tree_name(zFile, &fname, 0, 1); | |
| 304 | 304 | historical_version_of_file(zFrom, blob_str(&fname), &content, &isLink, 0, |
| 305 | 305 | fIncludeBinary ? 0 : &isBin, 0); |
| 306 | 306 | if( !isLink != !file_wd_islink(zFrom) ){ |
| 307 | 307 | fossil_print("%s",DIFF_CANNOT_COMPUTE_SYMLINK); |
| 308 | 308 | }else{ |
| 309 | - diff_file(&content, isBin, zFileTreeName, zFileTreeName, | |
| 309 | + diff_file(&content, isBin, zFile, zFile, | |
| 310 | 310 | zDiffCmd, zBinGlob, fIncludeBinary, diffFlags); |
| 311 | 311 | } |
| 312 | 312 | blob_reset(&content); |
| 313 | 313 | blob_reset(&fname); |
| 314 | 314 | } |
| @@ -427,10 +427,68 @@ | ||
| 427 | 427 | free(zToFree); |
| 428 | 428 | } |
| 429 | 429 | db_finalize(&q); |
| 430 | 430 | db_end_transaction(1); /* ROLLBACK */ |
| 431 | 431 | } |
| 432 | + | |
| 433 | +/* | |
| 434 | +** Do a diff of a single file named in zFile against the | |
| 435 | +** version of this file held in the undo buffer. | |
| 436 | +** | |
| 437 | +** Use the internal diff logic if zDiffCmd is NULL. Otherwise call the | |
| 438 | +** command zDiffCmd to do the diffing. | |
| 439 | +** | |
| 440 | +** When using an external diff program, zBinGlob contains the GLOB patterns | |
| 441 | +** for file names to treat as binary. If fIncludeBinary is zero, these files | |
| 442 | +** will be skipped in addition to files that may contain binary content. | |
| 443 | +*/ | |
| 444 | +static void diff_one_against_undo( | |
| 445 | + const char *zDiffCmd, /* Use this "diff" command */ | |
| 446 | + const char *zBinGlob, /* Treat file names matching this as binary */ | |
| 447 | + int fIncludeBinary, /* Include binary files for external diff */ | |
| 448 | + u64 diffFlags, /* Diff control flags */ | |
| 449 | + const char *zFile /* Name of the file to be diffed */ | |
| 450 | +){ | |
| 451 | + Blob fname; | |
| 452 | + Blob content; | |
| 453 | + | |
| 454 | + blob_init(&content, 0, 0); | |
| 455 | + file_tree_name(zFile, &fname, 0, 1); | |
| 456 | + db_blob(&content, "SELECT content FROM undo WHERE pathname=%Q", | |
| 457 | + blob_str(&fname)); | |
| 458 | + if( blob_size(&content) ){ | |
| 459 | + diff_file(&content, 0, zFile, zFile, | |
| 460 | + zDiffCmd, zBinGlob, fIncludeBinary, diffFlags); | |
| 461 | + } | |
| 462 | + blob_reset(&content); | |
| 463 | + blob_reset(&fname); | |
| 464 | +} | |
| 465 | + | |
| 466 | +/* | |
| 467 | +** Run a diff between the undo buffer and files on disk. | |
| 468 | +** | |
| 469 | +** Use the internal diff logic if zDiffCmd is NULL. Otherwise call the | |
| 470 | +** command zDiffCmd to do the diffing. | |
| 471 | +** | |
| 472 | +** When using an external diff program, zBinGlob contains the GLOB patterns | |
| 473 | +** for file names to treat as binary. If fIncludeBinary is zero, these files | |
| 474 | +** will be skipped in addition to files that may contain binary content. | |
| 475 | +*/ | |
| 476 | +static void diff_all_against_undo( | |
| 477 | + const char *zDiffCmd, /* Use this diff command. NULL for built-in */ | |
| 478 | + const char *zBinGlob, /* Treat file names matching this as binary */ | |
| 479 | + int fIncludeBinary, /* Treat file names matching this as binary */ | |
| 480 | + u64 diffFlags /* Flags controlling diff output */ | |
| 481 | +){ | |
| 482 | + Stmt q; | |
| 483 | + db_prepare(&q, "SELECT pathname FROM undo"); | |
| 484 | + while( db_step(&q)==SQLITE_ROW ){ | |
| 485 | + diff_one_against_undo(zDiffCmd, zBinGlob, fIncludeBinary, diffFlags, | |
| 486 | + db_column_text(&q, 0)); | |
| 487 | + } | |
| 488 | + db_finalize(&q); | |
| 489 | +} | |
| 432 | 490 | |
| 433 | 491 | /* |
| 434 | 492 | ** Output the differences between two versions of a single file. |
| 435 | 493 | ** zFrom and zTo are the check-ins containing the two file versions. |
| 436 | 494 | ** |
| @@ -446,19 +504,19 @@ | ||
| 446 | 504 | const char *zTo, /* Version tag for the "after" file */ |
| 447 | 505 | const char *zDiffCmd, /* Use this "diff" command */ |
| 448 | 506 | const char *zBinGlob, /* GLOB pattern for files that are binary */ |
| 449 | 507 | int fIncludeBinary, /* True to show binary files */ |
| 450 | 508 | u64 diffFlags, /* Diff flags */ |
| 451 | - const char *zFileTreeName /* Name of the file to be diffed */ | |
| 509 | + const char *zFile /* Name of the file to be diffed */ | |
| 452 | 510 | ){ |
| 453 | 511 | char *zName; |
| 454 | 512 | Blob fname; |
| 455 | 513 | Blob v1, v2; |
| 456 | 514 | int isLink1, isLink2; |
| 457 | 515 | int isBin1, isBin2; |
| 458 | 516 | if( diffFlags & DIFF_BRIEF ) return; |
| 459 | - file_tree_name(zFileTreeName, &fname, 0, 1); | |
| 517 | + file_tree_name(zFile, &fname, 0, 1); | |
| 460 | 518 | zName = blob_str(&fname); |
| 461 | 519 | historical_version_of_file(zFrom, zName, &v1, &isLink1, 0, |
| 462 | 520 | fIncludeBinary ? 0 : &isBin1, 0); |
| 463 | 521 | historical_version_of_file(zTo, zName, &v2, &isLink2, 0, |
| 464 | 522 | fIncludeBinary ? 0 : &isBin2, 0); |
| @@ -753,10 +811,11 @@ | ||
| 753 | 811 | ** --internal|-i use internal diff logic |
| 754 | 812 | ** --side-by-side|-y side-by-side diff |
| 755 | 813 | ** --strip-trailing-cr Strip trailing CR |
| 756 | 814 | ** --tk Launch a Tcl/Tk GUI for display |
| 757 | 815 | ** --to VERSION select VERSION as target for the diff |
| 816 | +** --undo Diff against the "undo" buffer | |
| 758 | 817 | ** --unified unified diff |
| 759 | 818 | ** -v|--verbose output complete text of added or deleted files |
| 760 | 819 | ** -w|--ignore-all-space Ignore white space when comparing lines |
| 761 | 820 | ** -W|--width <num> Width of lines in side-by-side diff |
| 762 | 821 | ** -Z|--ignore-trailing-space Ignore changes to end-of-line whitespace |
| @@ -769,10 +828,11 @@ | ||
| 769 | 828 | const char *zTo; /* Target version number */ |
| 770 | 829 | const char *zBranch; /* Branch to diff */ |
| 771 | 830 | const char *zDiffCmd = 0; /* External diff command. NULL for internal diff */ |
| 772 | 831 | const char *zBinGlob = 0; /* Treat file names matching this as binary */ |
| 773 | 832 | int fIncludeBinary = 0; /* Include binary files for external diff */ |
| 833 | + int againstUndo = 0; /* Diff against files in the undo buffer */ | |
| 774 | 834 | u64 diffFlags = 0; /* Flags to control the DIFF */ |
| 775 | 835 | |
| 776 | 836 | if( find_option("tk",0,0)!=0 ){ |
| 777 | 837 | diff_tk("diff", 2); |
| 778 | 838 | return; |
| @@ -780,31 +840,56 @@ | ||
| 780 | 840 | isGDiff = g.argv[1][0]=='g'; |
| 781 | 841 | isInternDiff = find_option("internal","i",0)!=0; |
| 782 | 842 | zFrom = find_option("from", "r", 1); |
| 783 | 843 | zTo = find_option("to", 0, 1); |
| 784 | 844 | zBranch = find_option("branch", 0, 1); |
| 845 | + againstUndo = find_option("undo",0,0)!=0; | |
| 785 | 846 | diffFlags = diff_options(); |
| 786 | 847 | verboseFlag = find_option("verbose","v",0)!=0; |
| 787 | 848 | if( !verboseFlag ){ |
| 788 | 849 | verboseFlag = find_option("new-file","N",0)!=0; /* deprecated */ |
| 789 | 850 | } |
| 790 | 851 | if( verboseFlag ) diffFlags |= DIFF_VERBOSE; |
| 852 | + if( againstUndo && (zFrom!=0 || zTo!=0 || zBranch!=0) ){ | |
| 853 | + fossil_fatal("cannot use --undo together with --from or --to or --branch"); | |
| 854 | + } | |
| 791 | 855 | if( zBranch ){ |
| 792 | 856 | if( zTo || zFrom ){ |
| 793 | 857 | fossil_fatal("cannot use --from or --to with --branch"); |
| 794 | 858 | } |
| 795 | 859 | zTo = zBranch; |
| 796 | 860 | zFrom = mprintf("root:%s", zBranch); |
| 797 | 861 | } |
| 798 | - if( zTo==0 ){ | |
| 862 | + if( zTo==0 || againstUndo ){ | |
| 799 | 863 | db_must_be_within_tree(); |
| 800 | - if( !isInternDiff ){ | |
| 801 | - zDiffCmd = diff_command_external(isGDiff); | |
| 864 | + }else if( zFrom==0 ){ | |
| 865 | + fossil_fatal("must use --from if --to is present"); | |
| 866 | + }else{ | |
| 867 | + db_find_and_open_repository(0, 0); | |
| 868 | + } | |
| 869 | + if( !isInternDiff ){ | |
| 870 | + zDiffCmd = diff_command_external(isGDiff); | |
| 871 | + } | |
| 872 | + zBinGlob = diff_get_binary_glob(); | |
| 873 | + fIncludeBinary = diff_include_binary_files(); | |
| 874 | + verify_all_options(); | |
| 875 | + if( againstUndo ){ | |
| 876 | + if( db_lget_int("undo_available",0)==0 ){ | |
| 877 | + fossil_print("No undo or redo is available\n"); | |
| 878 | + return; | |
| 879 | + } | |
| 880 | + if( g.argc>=3 ){ | |
| 881 | + int i; | |
| 882 | + for(i=2; i<g.argc; i++){ | |
| 883 | + diff_one_against_undo(zDiffCmd, zBinGlob, fIncludeBinary, | |
| 884 | + diffFlags, g.argv[i]); | |
| 885 | + } | |
| 886 | + }else{ | |
| 887 | + diff_all_against_undo(zDiffCmd, zBinGlob, fIncludeBinary, | |
| 888 | + diffFlags); | |
| 802 | 889 | } |
| 803 | - zBinGlob = diff_get_binary_glob(); | |
| 804 | - fIncludeBinary = diff_include_binary_files(); | |
| 805 | - verify_all_options(); | |
| 890 | + }else if( zTo==0 ){ | |
| 806 | 891 | if( g.argc>=3 ){ |
| 807 | 892 | int i; |
| 808 | 893 | for(i=2; i<g.argc; i++){ |
| 809 | 894 | diff_one_against_disk(zFrom, zDiffCmd, zBinGlob, fIncludeBinary, |
| 810 | 895 | diffFlags, g.argv[i]); |
| @@ -811,20 +896,11 @@ | ||
| 811 | 896 | } |
| 812 | 897 | }else{ |
| 813 | 898 | diff_all_against_disk(zFrom, zDiffCmd, zBinGlob, fIncludeBinary, |
| 814 | 899 | diffFlags); |
| 815 | 900 | } |
| 816 | - }else if( zFrom==0 ){ | |
| 817 | - fossil_fatal("must use --from if --to is present"); | |
| 818 | 901 | }else{ |
| 819 | - db_find_and_open_repository(0, 0); | |
| 820 | - if( !isInternDiff ){ | |
| 821 | - zDiffCmd = diff_command_external(isGDiff); | |
| 822 | - } | |
| 823 | - zBinGlob = diff_get_binary_glob(); | |
| 824 | - fIncludeBinary = diff_include_binary_files(); | |
| 825 | - verify_all_options(); | |
| 826 | 902 | if( g.argc>=3 ){ |
| 827 | 903 | int i; |
| 828 | 904 | for(i=2; i<g.argc; i++){ |
| 829 | 905 | diff_one_two_versions(zFrom, zTo, zDiffCmd, zBinGlob, fIncludeBinary, |
| 830 | 906 | diffFlags, g.argv[i]); |
| 831 | 907 |
| --- src/diffcmd.c | |
| +++ src/diffcmd.c | |
| @@ -276,11 +276,11 @@ | |
| 276 | blob_reset(&cmd); |
| 277 | } |
| 278 | } |
| 279 | |
| 280 | /* |
| 281 | ** Do a diff against a single file named in zFileTreeName from version zFrom |
| 282 | ** against the same file on disk. |
| 283 | ** |
| 284 | ** Use the internal diff logic if zDiffCmd is NULL. Otherwise call the |
| 285 | ** command zDiffCmd to do the diffing. |
| 286 | ** |
| @@ -292,23 +292,23 @@ | |
| 292 | const char *zFrom, /* Version tag for the "before" file */ |
| 293 | const char *zDiffCmd, /* Use this "diff" command */ |
| 294 | const char *zBinGlob, /* Treat file names matching this as binary */ |
| 295 | int fIncludeBinary, /* Include binary files for external diff */ |
| 296 | u64 diffFlags, /* Diff control flags */ |
| 297 | const char *zFileTreeName /* Name of the file to be diffed */ |
| 298 | ){ |
| 299 | Blob fname; |
| 300 | Blob content; |
| 301 | int isLink; |
| 302 | int isBin; |
| 303 | file_tree_name(zFileTreeName, &fname, 0, 1); |
| 304 | historical_version_of_file(zFrom, blob_str(&fname), &content, &isLink, 0, |
| 305 | fIncludeBinary ? 0 : &isBin, 0); |
| 306 | if( !isLink != !file_wd_islink(zFrom) ){ |
| 307 | fossil_print("%s",DIFF_CANNOT_COMPUTE_SYMLINK); |
| 308 | }else{ |
| 309 | diff_file(&content, isBin, zFileTreeName, zFileTreeName, |
| 310 | zDiffCmd, zBinGlob, fIncludeBinary, diffFlags); |
| 311 | } |
| 312 | blob_reset(&content); |
| 313 | blob_reset(&fname); |
| 314 | } |
| @@ -427,10 +427,68 @@ | |
| 427 | free(zToFree); |
| 428 | } |
| 429 | db_finalize(&q); |
| 430 | db_end_transaction(1); /* ROLLBACK */ |
| 431 | } |
| 432 | |
| 433 | /* |
| 434 | ** Output the differences between two versions of a single file. |
| 435 | ** zFrom and zTo are the check-ins containing the two file versions. |
| 436 | ** |
| @@ -446,19 +504,19 @@ | |
| 446 | const char *zTo, /* Version tag for the "after" file */ |
| 447 | const char *zDiffCmd, /* Use this "diff" command */ |
| 448 | const char *zBinGlob, /* GLOB pattern for files that are binary */ |
| 449 | int fIncludeBinary, /* True to show binary files */ |
| 450 | u64 diffFlags, /* Diff flags */ |
| 451 | const char *zFileTreeName /* Name of the file to be diffed */ |
| 452 | ){ |
| 453 | char *zName; |
| 454 | Blob fname; |
| 455 | Blob v1, v2; |
| 456 | int isLink1, isLink2; |
| 457 | int isBin1, isBin2; |
| 458 | if( diffFlags & DIFF_BRIEF ) return; |
| 459 | file_tree_name(zFileTreeName, &fname, 0, 1); |
| 460 | zName = blob_str(&fname); |
| 461 | historical_version_of_file(zFrom, zName, &v1, &isLink1, 0, |
| 462 | fIncludeBinary ? 0 : &isBin1, 0); |
| 463 | historical_version_of_file(zTo, zName, &v2, &isLink2, 0, |
| 464 | fIncludeBinary ? 0 : &isBin2, 0); |
| @@ -753,10 +811,11 @@ | |
| 753 | ** --internal|-i use internal diff logic |
| 754 | ** --side-by-side|-y side-by-side diff |
| 755 | ** --strip-trailing-cr Strip trailing CR |
| 756 | ** --tk Launch a Tcl/Tk GUI for display |
| 757 | ** --to VERSION select VERSION as target for the diff |
| 758 | ** --unified unified diff |
| 759 | ** -v|--verbose output complete text of added or deleted files |
| 760 | ** -w|--ignore-all-space Ignore white space when comparing lines |
| 761 | ** -W|--width <num> Width of lines in side-by-side diff |
| 762 | ** -Z|--ignore-trailing-space Ignore changes to end-of-line whitespace |
| @@ -769,10 +828,11 @@ | |
| 769 | const char *zTo; /* Target version number */ |
| 770 | const char *zBranch; /* Branch to diff */ |
| 771 | const char *zDiffCmd = 0; /* External diff command. NULL for internal diff */ |
| 772 | const char *zBinGlob = 0; /* Treat file names matching this as binary */ |
| 773 | int fIncludeBinary = 0; /* Include binary files for external diff */ |
| 774 | u64 diffFlags = 0; /* Flags to control the DIFF */ |
| 775 | |
| 776 | if( find_option("tk",0,0)!=0 ){ |
| 777 | diff_tk("diff", 2); |
| 778 | return; |
| @@ -780,31 +840,56 @@ | |
| 780 | isGDiff = g.argv[1][0]=='g'; |
| 781 | isInternDiff = find_option("internal","i",0)!=0; |
| 782 | zFrom = find_option("from", "r", 1); |
| 783 | zTo = find_option("to", 0, 1); |
| 784 | zBranch = find_option("branch", 0, 1); |
| 785 | diffFlags = diff_options(); |
| 786 | verboseFlag = find_option("verbose","v",0)!=0; |
| 787 | if( !verboseFlag ){ |
| 788 | verboseFlag = find_option("new-file","N",0)!=0; /* deprecated */ |
| 789 | } |
| 790 | if( verboseFlag ) diffFlags |= DIFF_VERBOSE; |
| 791 | if( zBranch ){ |
| 792 | if( zTo || zFrom ){ |
| 793 | fossil_fatal("cannot use --from or --to with --branch"); |
| 794 | } |
| 795 | zTo = zBranch; |
| 796 | zFrom = mprintf("root:%s", zBranch); |
| 797 | } |
| 798 | if( zTo==0 ){ |
| 799 | db_must_be_within_tree(); |
| 800 | if( !isInternDiff ){ |
| 801 | zDiffCmd = diff_command_external(isGDiff); |
| 802 | } |
| 803 | zBinGlob = diff_get_binary_glob(); |
| 804 | fIncludeBinary = diff_include_binary_files(); |
| 805 | verify_all_options(); |
| 806 | if( g.argc>=3 ){ |
| 807 | int i; |
| 808 | for(i=2; i<g.argc; i++){ |
| 809 | diff_one_against_disk(zFrom, zDiffCmd, zBinGlob, fIncludeBinary, |
| 810 | diffFlags, g.argv[i]); |
| @@ -811,20 +896,11 @@ | |
| 811 | } |
| 812 | }else{ |
| 813 | diff_all_against_disk(zFrom, zDiffCmd, zBinGlob, fIncludeBinary, |
| 814 | diffFlags); |
| 815 | } |
| 816 | }else if( zFrom==0 ){ |
| 817 | fossil_fatal("must use --from if --to is present"); |
| 818 | }else{ |
| 819 | db_find_and_open_repository(0, 0); |
| 820 | if( !isInternDiff ){ |
| 821 | zDiffCmd = diff_command_external(isGDiff); |
| 822 | } |
| 823 | zBinGlob = diff_get_binary_glob(); |
| 824 | fIncludeBinary = diff_include_binary_files(); |
| 825 | verify_all_options(); |
| 826 | if( g.argc>=3 ){ |
| 827 | int i; |
| 828 | for(i=2; i<g.argc; i++){ |
| 829 | diff_one_two_versions(zFrom, zTo, zDiffCmd, zBinGlob, fIncludeBinary, |
| 830 | diffFlags, g.argv[i]); |
| 831 |
| --- src/diffcmd.c | |
| +++ src/diffcmd.c | |
| @@ -276,11 +276,11 @@ | |
| 276 | blob_reset(&cmd); |
| 277 | } |
| 278 | } |
| 279 | |
| 280 | /* |
| 281 | ** Do a diff against a single file named in zFile from version zFrom |
| 282 | ** against the same file on disk. |
| 283 | ** |
| 284 | ** Use the internal diff logic if zDiffCmd is NULL. Otherwise call the |
| 285 | ** command zDiffCmd to do the diffing. |
| 286 | ** |
| @@ -292,23 +292,23 @@ | |
| 292 | const char *zFrom, /* Version tag for the "before" file */ |
| 293 | const char *zDiffCmd, /* Use this "diff" command */ |
| 294 | const char *zBinGlob, /* Treat file names matching this as binary */ |
| 295 | int fIncludeBinary, /* Include binary files for external diff */ |
| 296 | u64 diffFlags, /* Diff control flags */ |
| 297 | const char *zFile /* Name of the file to be diffed */ |
| 298 | ){ |
| 299 | Blob fname; |
| 300 | Blob content; |
| 301 | int isLink; |
| 302 | int isBin; |
| 303 | file_tree_name(zFile, &fname, 0, 1); |
| 304 | historical_version_of_file(zFrom, blob_str(&fname), &content, &isLink, 0, |
| 305 | fIncludeBinary ? 0 : &isBin, 0); |
| 306 | if( !isLink != !file_wd_islink(zFrom) ){ |
| 307 | fossil_print("%s",DIFF_CANNOT_COMPUTE_SYMLINK); |
| 308 | }else{ |
| 309 | diff_file(&content, isBin, zFile, zFile, |
| 310 | zDiffCmd, zBinGlob, fIncludeBinary, diffFlags); |
| 311 | } |
| 312 | blob_reset(&content); |
| 313 | blob_reset(&fname); |
| 314 | } |
| @@ -427,10 +427,68 @@ | |
| 427 | free(zToFree); |
| 428 | } |
| 429 | db_finalize(&q); |
| 430 | db_end_transaction(1); /* ROLLBACK */ |
| 431 | } |
| 432 | |
| 433 | /* |
| 434 | ** Do a diff of a single file named in zFile against the |
| 435 | ** version of this file held in the undo buffer. |
| 436 | ** |
| 437 | ** Use the internal diff logic if zDiffCmd is NULL. Otherwise call the |
| 438 | ** command zDiffCmd to do the diffing. |
| 439 | ** |
| 440 | ** When using an external diff program, zBinGlob contains the GLOB patterns |
| 441 | ** for file names to treat as binary. If fIncludeBinary is zero, these files |
| 442 | ** will be skipped in addition to files that may contain binary content. |
| 443 | */ |
| 444 | static void diff_one_against_undo( |
| 445 | const char *zDiffCmd, /* Use this "diff" command */ |
| 446 | const char *zBinGlob, /* Treat file names matching this as binary */ |
| 447 | int fIncludeBinary, /* Include binary files for external diff */ |
| 448 | u64 diffFlags, /* Diff control flags */ |
| 449 | const char *zFile /* Name of the file to be diffed */ |
| 450 | ){ |
| 451 | Blob fname; |
| 452 | Blob content; |
| 453 | |
| 454 | blob_init(&content, 0, 0); |
| 455 | file_tree_name(zFile, &fname, 0, 1); |
| 456 | db_blob(&content, "SELECT content FROM undo WHERE pathname=%Q", |
| 457 | blob_str(&fname)); |
| 458 | if( blob_size(&content) ){ |
| 459 | diff_file(&content, 0, zFile, zFile, |
| 460 | zDiffCmd, zBinGlob, fIncludeBinary, diffFlags); |
| 461 | } |
| 462 | blob_reset(&content); |
| 463 | blob_reset(&fname); |
| 464 | } |
| 465 | |
| 466 | /* |
| 467 | ** Run a diff between the undo buffer and files on disk. |
| 468 | ** |
| 469 | ** Use the internal diff logic if zDiffCmd is NULL. Otherwise call the |
| 470 | ** command zDiffCmd to do the diffing. |
| 471 | ** |
| 472 | ** When using an external diff program, zBinGlob contains the GLOB patterns |
| 473 | ** for file names to treat as binary. If fIncludeBinary is zero, these files |
| 474 | ** will be skipped in addition to files that may contain binary content. |
| 475 | */ |
| 476 | static void diff_all_against_undo( |
| 477 | const char *zDiffCmd, /* Use this diff command. NULL for built-in */ |
| 478 | const char *zBinGlob, /* Treat file names matching this as binary */ |
| 479 | int fIncludeBinary, /* Treat file names matching this as binary */ |
| 480 | u64 diffFlags /* Flags controlling diff output */ |
| 481 | ){ |
| 482 | Stmt q; |
| 483 | db_prepare(&q, "SELECT pathname FROM undo"); |
| 484 | while( db_step(&q)==SQLITE_ROW ){ |
| 485 | diff_one_against_undo(zDiffCmd, zBinGlob, fIncludeBinary, diffFlags, |
| 486 | db_column_text(&q, 0)); |
| 487 | } |
| 488 | db_finalize(&q); |
| 489 | } |
| 490 | |
| 491 | /* |
| 492 | ** Output the differences between two versions of a single file. |
| 493 | ** zFrom and zTo are the check-ins containing the two file versions. |
| 494 | ** |
| @@ -446,19 +504,19 @@ | |
| 504 | const char *zTo, /* Version tag for the "after" file */ |
| 505 | const char *zDiffCmd, /* Use this "diff" command */ |
| 506 | const char *zBinGlob, /* GLOB pattern for files that are binary */ |
| 507 | int fIncludeBinary, /* True to show binary files */ |
| 508 | u64 diffFlags, /* Diff flags */ |
| 509 | const char *zFile /* Name of the file to be diffed */ |
| 510 | ){ |
| 511 | char *zName; |
| 512 | Blob fname; |
| 513 | Blob v1, v2; |
| 514 | int isLink1, isLink2; |
| 515 | int isBin1, isBin2; |
| 516 | if( diffFlags & DIFF_BRIEF ) return; |
| 517 | file_tree_name(zFile, &fname, 0, 1); |
| 518 | zName = blob_str(&fname); |
| 519 | historical_version_of_file(zFrom, zName, &v1, &isLink1, 0, |
| 520 | fIncludeBinary ? 0 : &isBin1, 0); |
| 521 | historical_version_of_file(zTo, zName, &v2, &isLink2, 0, |
| 522 | fIncludeBinary ? 0 : &isBin2, 0); |
| @@ -753,10 +811,11 @@ | |
| 811 | ** --internal|-i use internal diff logic |
| 812 | ** --side-by-side|-y side-by-side diff |
| 813 | ** --strip-trailing-cr Strip trailing CR |
| 814 | ** --tk Launch a Tcl/Tk GUI for display |
| 815 | ** --to VERSION select VERSION as target for the diff |
| 816 | ** --undo Diff against the "undo" buffer |
| 817 | ** --unified unified diff |
| 818 | ** -v|--verbose output complete text of added or deleted files |
| 819 | ** -w|--ignore-all-space Ignore white space when comparing lines |
| 820 | ** -W|--width <num> Width of lines in side-by-side diff |
| 821 | ** -Z|--ignore-trailing-space Ignore changes to end-of-line whitespace |
| @@ -769,10 +828,11 @@ | |
| 828 | const char *zTo; /* Target version number */ |
| 829 | const char *zBranch; /* Branch to diff */ |
| 830 | const char *zDiffCmd = 0; /* External diff command. NULL for internal diff */ |
| 831 | const char *zBinGlob = 0; /* Treat file names matching this as binary */ |
| 832 | int fIncludeBinary = 0; /* Include binary files for external diff */ |
| 833 | int againstUndo = 0; /* Diff against files in the undo buffer */ |
| 834 | u64 diffFlags = 0; /* Flags to control the DIFF */ |
| 835 | |
| 836 | if( find_option("tk",0,0)!=0 ){ |
| 837 | diff_tk("diff", 2); |
| 838 | return; |
| @@ -780,31 +840,56 @@ | |
| 840 | isGDiff = g.argv[1][0]=='g'; |
| 841 | isInternDiff = find_option("internal","i",0)!=0; |
| 842 | zFrom = find_option("from", "r", 1); |
| 843 | zTo = find_option("to", 0, 1); |
| 844 | zBranch = find_option("branch", 0, 1); |
| 845 | againstUndo = find_option("undo",0,0)!=0; |
| 846 | diffFlags = diff_options(); |
| 847 | verboseFlag = find_option("verbose","v",0)!=0; |
| 848 | if( !verboseFlag ){ |
| 849 | verboseFlag = find_option("new-file","N",0)!=0; /* deprecated */ |
| 850 | } |
| 851 | if( verboseFlag ) diffFlags |= DIFF_VERBOSE; |
| 852 | if( againstUndo && (zFrom!=0 || zTo!=0 || zBranch!=0) ){ |
| 853 | fossil_fatal("cannot use --undo together with --from or --to or --branch"); |
| 854 | } |
| 855 | if( zBranch ){ |
| 856 | if( zTo || zFrom ){ |
| 857 | fossil_fatal("cannot use --from or --to with --branch"); |
| 858 | } |
| 859 | zTo = zBranch; |
| 860 | zFrom = mprintf("root:%s", zBranch); |
| 861 | } |
| 862 | if( zTo==0 || againstUndo ){ |
| 863 | db_must_be_within_tree(); |
| 864 | }else if( zFrom==0 ){ |
| 865 | fossil_fatal("must use --from if --to is present"); |
| 866 | }else{ |
| 867 | db_find_and_open_repository(0, 0); |
| 868 | } |
| 869 | if( !isInternDiff ){ |
| 870 | zDiffCmd = diff_command_external(isGDiff); |
| 871 | } |
| 872 | zBinGlob = diff_get_binary_glob(); |
| 873 | fIncludeBinary = diff_include_binary_files(); |
| 874 | verify_all_options(); |
| 875 | if( againstUndo ){ |
| 876 | if( db_lget_int("undo_available",0)==0 ){ |
| 877 | fossil_print("No undo or redo is available\n"); |
| 878 | return; |
| 879 | } |
| 880 | if( g.argc>=3 ){ |
| 881 | int i; |
| 882 | for(i=2; i<g.argc; i++){ |
| 883 | diff_one_against_undo(zDiffCmd, zBinGlob, fIncludeBinary, |
| 884 | diffFlags, g.argv[i]); |
| 885 | } |
| 886 | }else{ |
| 887 | diff_all_against_undo(zDiffCmd, zBinGlob, fIncludeBinary, |
| 888 | diffFlags); |
| 889 | } |
| 890 | }else if( zTo==0 ){ |
| 891 | if( g.argc>=3 ){ |
| 892 | int i; |
| 893 | for(i=2; i<g.argc; i++){ |
| 894 | diff_one_against_disk(zFrom, zDiffCmd, zBinGlob, fIncludeBinary, |
| 895 | diffFlags, g.argv[i]); |
| @@ -811,20 +896,11 @@ | |
| 896 | } |
| 897 | }else{ |
| 898 | diff_all_against_disk(zFrom, zDiffCmd, zBinGlob, fIncludeBinary, |
| 899 | diffFlags); |
| 900 | } |
| 901 | }else{ |
| 902 | if( g.argc>=3 ){ |
| 903 | int i; |
| 904 | for(i=2; i<g.argc; i++){ |
| 905 | diff_one_two_versions(zFrom, zTo, zDiffCmd, zBinGlob, fIncludeBinary, |
| 906 | diffFlags, g.argv[i]); |
| 907 |