Fossil SCM
Make it possible to undo the deletion of files less than 10MiB by the clean command. This branch is an alternative to the 'undo-clean' branch. Needs tests.
Commit
7794b21695e7dc8952e54555fefd9099ebd84650
Parent
670da77e1abd650…
2 files changed
+46
-19
+25
-4
+46
-19
| --- src/checkin.c | ||
| +++ src/checkin.c | ||
| @@ -644,11 +644,12 @@ | ||
| 644 | 644 | ** Files and subdirectories whose names begin with "." are automatically |
| 645 | 645 | ** ignored unless the --dotfiles option is used. |
| 646 | 646 | ** |
| 647 | 647 | ** The --verily option ignores the keep-glob and ignore-glob settings |
| 648 | 648 | ** and turns on --force, --dotfiles, and --emptydirs. Use the --verily |
| 649 | -** option when you really want to clean up everything. | |
| 649 | +** option when you really want to clean up everything. Extreme care | |
| 650 | +** should be exercised when using the --verily option. | |
| 650 | 651 | ** |
| 651 | 652 | ** Options: |
| 652 | 653 | ** --allckouts Check for empty directories within any checkouts |
| 653 | 654 | ** that may be nested within the current one. This |
| 654 | 655 | ** option should be used with great care because the |
| @@ -657,24 +658,32 @@ | ||
| 657 | 658 | ** not be checked. |
| 658 | 659 | ** --case-sensitive <BOOL> override case-sensitive setting |
| 659 | 660 | ** --dirsonly Only remove empty directories. No files will |
| 660 | 661 | ** be removed. Using this option will automatically |
| 661 | 662 | ** enable the --emptydirs option as well. |
| 663 | +** --disable-undo WARNING: This option disables use of the undo | |
| 664 | +** mechanism for this clean operation and should be | |
| 665 | +** used with extreme caution. | |
| 662 | 666 | ** --dotfiles Include files beginning with a dot ("."). |
| 663 | 667 | ** --emptydirs Remove any empty directories that are not |
| 664 | 668 | ** explicitly exempted via the empty-dirs setting |
| 665 | 669 | ** or another applicable setting or command line |
| 666 | 670 | ** argument. Matching files, if any, are removed |
| 667 | 671 | ** prior to checking for any empty directories; |
| 668 | 672 | ** therefore, directories that contain only files |
| 669 | 673 | ** that were removed will be removed as well. |
| 670 | 674 | ** -f|--force Remove files without prompting. |
| 671 | -** -x|--verily Remove everything that is not a managed file or | |
| 672 | -** the repository itself. Implies -f --emptydirs | |
| 673 | -** --dotfiles. Disregard keep-glob and ignore-glob. | |
| 674 | -** --clean <CSG> Never prompt for files matching this | |
| 675 | -** comma separated list of glob patterns. | |
| 675 | +** -x|--verily WARNING: Remove everything that is not a managed | |
| 676 | +** file or the repository itself. This option | |
| 677 | +** implies the --force, --emptydirs, and --dotfiles | |
| 678 | +** options. Furthermore, it completely disregards | |
| 679 | +** the keep-glob and ignore-glob settings. However, | |
| 680 | +** it does honor the --ignore and --keep options. | |
| 681 | +** --clean <CSG> WARNING: Never prompt to delete any files matching | |
| 682 | +** this comma separated list of glob patterns. Also, | |
| 683 | +** deletions of any files matching this pattern list | |
| 684 | +** cannot be undone. | |
| 676 | 685 | ** --ignore <CSG> Ignore files matching patterns from the |
| 677 | 686 | ** comma separated list of glob patterns. |
| 678 | 687 | ** --keep <CSG> Keep files matching this comma separated |
| 679 | 688 | ** list of glob patterns. |
| 680 | 689 | ** -n|--dry-run Delete nothing, but display what would have been |
| @@ -685,23 +694,30 @@ | ||
| 685 | 694 | ** See also: addremove, extras, status |
| 686 | 695 | */ |
| 687 | 696 | void clean_cmd(void){ |
| 688 | 697 | int allFileFlag, allDirFlag, dryRunFlag, verboseFlag; |
| 689 | 698 | int emptyDirsFlag, dirsOnlyFlag; |
| 699 | + int disableUndo; | |
| 690 | 700 | unsigned scanFlags = 0; |
| 691 | 701 | int verilyFlag = 0; |
| 692 | 702 | const char *zIgnoreFlag, *zKeepFlag, *zCleanFlag; |
| 693 | 703 | Glob *pIgnore, *pKeep, *pClean; |
| 694 | 704 | int nRoot; |
| 695 | 705 | |
| 706 | +#ifndef UNDO_SIZE_LIMIT /* TODO: Setting? */ | |
| 707 | +#define UNDO_SIZE_LIMIT (10*1024*1024) /* 10MiB */ | |
| 708 | +#endif | |
| 709 | + | |
| 710 | + undo_capture_command_line(); | |
| 696 | 711 | dryRunFlag = find_option("dry-run","n",0)!=0; |
| 697 | 712 | if( !dryRunFlag ){ |
| 698 | 713 | dryRunFlag = find_option("test",0,0)!=0; /* deprecated */ |
| 699 | 714 | } |
| 700 | 715 | if( !dryRunFlag ){ |
| 701 | 716 | dryRunFlag = find_option("whatif",0,0)!=0; |
| 702 | 717 | } |
| 718 | + disableUndo = find_option("disable-undo",0,0)!=0; | |
| 703 | 719 | allFileFlag = allDirFlag = find_option("force","f",0)!=0; |
| 704 | 720 | dirsOnlyFlag = find_option("dirsonly",0,0)!=0; |
| 705 | 721 | emptyDirsFlag = find_option("emptydirs","d",0)!=0 || dirsOnlyFlag; |
| 706 | 722 | if( find_option("dotfiles",0,0)!=0 ) scanFlags |= SCAN_ALL; |
| 707 | 723 | if( find_option("temp",0,0)!=0 ) scanFlags |= SCAN_TEMP; |
| @@ -734,10 +750,11 @@ | ||
| 734 | 750 | nRoot = (int)strlen(g.zLocalRoot); |
| 735 | 751 | g.allowSymlinks = 1; /* Find symlinks too */ |
| 736 | 752 | if( !dirsOnlyFlag ){ |
| 737 | 753 | Stmt q; |
| 738 | 754 | Blob repo; |
| 755 | + if( !dryRunFlag && !disableUndo ) undo_begin(); | |
| 739 | 756 | locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore, 0); |
| 740 | 757 | db_prepare(&q, |
| 741 | 758 | "SELECT %Q || x FROM sfile" |
| 742 | 759 | " WHERE x NOT IN (%s)" |
| 743 | 760 | " ORDER BY 1", |
| @@ -755,23 +772,32 @@ | ||
| 755 | 772 | " or \"keep-glob\")\n", zName+nRoot); |
| 756 | 773 | } |
| 757 | 774 | continue; |
| 758 | 775 | } |
| 759 | 776 | if( !allFileFlag && !dryRunFlag && !glob_match(pClean, zName+nRoot) ){ |
| 760 | - Blob ans; | |
| 761 | - char cReply; | |
| 762 | - char *prompt = mprintf("Remove unmanaged file \"%s\" (a=all/y/N)? ", | |
| 763 | - zName+nRoot); | |
| 764 | - prompt_user(prompt, &ans); | |
| 765 | - cReply = blob_str(&ans)[0]; | |
| 766 | - if( cReply=='a' || cReply=='A' ){ | |
| 767 | - allFileFlag = 1; | |
| 768 | - }else if( cReply!='y' && cReply!='Y' ){ | |
| 769 | - blob_reset(&ans); | |
| 770 | - continue; | |
| 771 | - } | |
| 772 | - blob_reset(&ans); | |
| 777 | + int undoRc = UNDO_NONE; | |
| 778 | + if( !disableUndo ){ | |
| 779 | + undoRc = undo_maybe_save(zName+nRoot, UNDO_SIZE_LIMIT); | |
| 780 | + } | |
| 781 | + if( undoRc!=UNDO_SAVED_OK ){ | |
| 782 | + Blob ans; | |
| 783 | + char cReply; | |
| 784 | + char *prompt = mprintf("\nWARNING: Deletion of this file will " | |
| 785 | + "not be undoable via the 'undo'\n" | |
| 786 | + " command because %s.\n\n" | |
| 787 | + "Remove unmanaged file \"%s\" (a=all/y/N)? ", | |
| 788 | + undo_save_message(undoRc), zName+nRoot); | |
| 789 | + prompt_user(prompt, &ans); | |
| 790 | + cReply = blob_str(&ans)[0]; | |
| 791 | + if( cReply=='a' || cReply=='A' ){ | |
| 792 | + allFileFlag = 1; | |
| 793 | + }else if( cReply!='y' && cReply!='Y' ){ | |
| 794 | + blob_reset(&ans); | |
| 795 | + continue; | |
| 796 | + } | |
| 797 | + blob_reset(&ans); | |
| 798 | + } | |
| 773 | 799 | } |
| 774 | 800 | if( dryRunFlag || file_delete(zName)==0 ){ |
| 775 | 801 | if( verboseFlag || dryRunFlag ){ |
| 776 | 802 | fossil_print("Removed unmanaged file: %s\n", zName+nRoot); |
| 777 | 803 | } |
| @@ -778,10 +804,11 @@ | ||
| 778 | 804 | }else if( verboseFlag ){ |
| 779 | 805 | fossil_print("Could not remove file: %s\n", zName+nRoot); |
| 780 | 806 | } |
| 781 | 807 | } |
| 782 | 808 | db_finalize(&q); |
| 809 | + if( !dryRunFlag && !disableUndo ) undo_finish(); | |
| 783 | 810 | } |
| 784 | 811 | if( emptyDirsFlag ){ |
| 785 | 812 | Glob *pEmptyDirs = glob_create(db_get("empty-dirs", 0)); |
| 786 | 813 | Stmt q; |
| 787 | 814 | Blob root; |
| 788 | 815 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -644,11 +644,12 @@ | |
| 644 | ** Files and subdirectories whose names begin with "." are automatically |
| 645 | ** ignored unless the --dotfiles option is used. |
| 646 | ** |
| 647 | ** The --verily option ignores the keep-glob and ignore-glob settings |
| 648 | ** and turns on --force, --dotfiles, and --emptydirs. Use the --verily |
| 649 | ** option when you really want to clean up everything. |
| 650 | ** |
| 651 | ** Options: |
| 652 | ** --allckouts Check for empty directories within any checkouts |
| 653 | ** that may be nested within the current one. This |
| 654 | ** option should be used with great care because the |
| @@ -657,24 +658,32 @@ | |
| 657 | ** not be checked. |
| 658 | ** --case-sensitive <BOOL> override case-sensitive setting |
| 659 | ** --dirsonly Only remove empty directories. No files will |
| 660 | ** be removed. Using this option will automatically |
| 661 | ** enable the --emptydirs option as well. |
| 662 | ** --dotfiles Include files beginning with a dot ("."). |
| 663 | ** --emptydirs Remove any empty directories that are not |
| 664 | ** explicitly exempted via the empty-dirs setting |
| 665 | ** or another applicable setting or command line |
| 666 | ** argument. Matching files, if any, are removed |
| 667 | ** prior to checking for any empty directories; |
| 668 | ** therefore, directories that contain only files |
| 669 | ** that were removed will be removed as well. |
| 670 | ** -f|--force Remove files without prompting. |
| 671 | ** -x|--verily Remove everything that is not a managed file or |
| 672 | ** the repository itself. Implies -f --emptydirs |
| 673 | ** --dotfiles. Disregard keep-glob and ignore-glob. |
| 674 | ** --clean <CSG> Never prompt for files matching this |
| 675 | ** comma separated list of glob patterns. |
| 676 | ** --ignore <CSG> Ignore files matching patterns from the |
| 677 | ** comma separated list of glob patterns. |
| 678 | ** --keep <CSG> Keep files matching this comma separated |
| 679 | ** list of glob patterns. |
| 680 | ** -n|--dry-run Delete nothing, but display what would have been |
| @@ -685,23 +694,30 @@ | |
| 685 | ** See also: addremove, extras, status |
| 686 | */ |
| 687 | void clean_cmd(void){ |
| 688 | int allFileFlag, allDirFlag, dryRunFlag, verboseFlag; |
| 689 | int emptyDirsFlag, dirsOnlyFlag; |
| 690 | unsigned scanFlags = 0; |
| 691 | int verilyFlag = 0; |
| 692 | const char *zIgnoreFlag, *zKeepFlag, *zCleanFlag; |
| 693 | Glob *pIgnore, *pKeep, *pClean; |
| 694 | int nRoot; |
| 695 | |
| 696 | dryRunFlag = find_option("dry-run","n",0)!=0; |
| 697 | if( !dryRunFlag ){ |
| 698 | dryRunFlag = find_option("test",0,0)!=0; /* deprecated */ |
| 699 | } |
| 700 | if( !dryRunFlag ){ |
| 701 | dryRunFlag = find_option("whatif",0,0)!=0; |
| 702 | } |
| 703 | allFileFlag = allDirFlag = find_option("force","f",0)!=0; |
| 704 | dirsOnlyFlag = find_option("dirsonly",0,0)!=0; |
| 705 | emptyDirsFlag = find_option("emptydirs","d",0)!=0 || dirsOnlyFlag; |
| 706 | if( find_option("dotfiles",0,0)!=0 ) scanFlags |= SCAN_ALL; |
| 707 | if( find_option("temp",0,0)!=0 ) scanFlags |= SCAN_TEMP; |
| @@ -734,10 +750,11 @@ | |
| 734 | nRoot = (int)strlen(g.zLocalRoot); |
| 735 | g.allowSymlinks = 1; /* Find symlinks too */ |
| 736 | if( !dirsOnlyFlag ){ |
| 737 | Stmt q; |
| 738 | Blob repo; |
| 739 | locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore, 0); |
| 740 | db_prepare(&q, |
| 741 | "SELECT %Q || x FROM sfile" |
| 742 | " WHERE x NOT IN (%s)" |
| 743 | " ORDER BY 1", |
| @@ -755,23 +772,32 @@ | |
| 755 | " or \"keep-glob\")\n", zName+nRoot); |
| 756 | } |
| 757 | continue; |
| 758 | } |
| 759 | if( !allFileFlag && !dryRunFlag && !glob_match(pClean, zName+nRoot) ){ |
| 760 | Blob ans; |
| 761 | char cReply; |
| 762 | char *prompt = mprintf("Remove unmanaged file \"%s\" (a=all/y/N)? ", |
| 763 | zName+nRoot); |
| 764 | prompt_user(prompt, &ans); |
| 765 | cReply = blob_str(&ans)[0]; |
| 766 | if( cReply=='a' || cReply=='A' ){ |
| 767 | allFileFlag = 1; |
| 768 | }else if( cReply!='y' && cReply!='Y' ){ |
| 769 | blob_reset(&ans); |
| 770 | continue; |
| 771 | } |
| 772 | blob_reset(&ans); |
| 773 | } |
| 774 | if( dryRunFlag || file_delete(zName)==0 ){ |
| 775 | if( verboseFlag || dryRunFlag ){ |
| 776 | fossil_print("Removed unmanaged file: %s\n", zName+nRoot); |
| 777 | } |
| @@ -778,10 +804,11 @@ | |
| 778 | }else if( verboseFlag ){ |
| 779 | fossil_print("Could not remove file: %s\n", zName+nRoot); |
| 780 | } |
| 781 | } |
| 782 | db_finalize(&q); |
| 783 | } |
| 784 | if( emptyDirsFlag ){ |
| 785 | Glob *pEmptyDirs = glob_create(db_get("empty-dirs", 0)); |
| 786 | Stmt q; |
| 787 | Blob root; |
| 788 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -644,11 +644,12 @@ | |
| 644 | ** Files and subdirectories whose names begin with "." are automatically |
| 645 | ** ignored unless the --dotfiles option is used. |
| 646 | ** |
| 647 | ** The --verily option ignores the keep-glob and ignore-glob settings |
| 648 | ** and turns on --force, --dotfiles, and --emptydirs. Use the --verily |
| 649 | ** option when you really want to clean up everything. Extreme care |
| 650 | ** should be exercised when using the --verily option. |
| 651 | ** |
| 652 | ** Options: |
| 653 | ** --allckouts Check for empty directories within any checkouts |
| 654 | ** that may be nested within the current one. This |
| 655 | ** option should be used with great care because the |
| @@ -657,24 +658,32 @@ | |
| 658 | ** not be checked. |
| 659 | ** --case-sensitive <BOOL> override case-sensitive setting |
| 660 | ** --dirsonly Only remove empty directories. No files will |
| 661 | ** be removed. Using this option will automatically |
| 662 | ** enable the --emptydirs option as well. |
| 663 | ** --disable-undo WARNING: This option disables use of the undo |
| 664 | ** mechanism for this clean operation and should be |
| 665 | ** used with extreme caution. |
| 666 | ** --dotfiles Include files beginning with a dot ("."). |
| 667 | ** --emptydirs Remove any empty directories that are not |
| 668 | ** explicitly exempted via the empty-dirs setting |
| 669 | ** or another applicable setting or command line |
| 670 | ** argument. Matching files, if any, are removed |
| 671 | ** prior to checking for any empty directories; |
| 672 | ** therefore, directories that contain only files |
| 673 | ** that were removed will be removed as well. |
| 674 | ** -f|--force Remove files without prompting. |
| 675 | ** -x|--verily WARNING: Remove everything that is not a managed |
| 676 | ** file or the repository itself. This option |
| 677 | ** implies the --force, --emptydirs, and --dotfiles |
| 678 | ** options. Furthermore, it completely disregards |
| 679 | ** the keep-glob and ignore-glob settings. However, |
| 680 | ** it does honor the --ignore and --keep options. |
| 681 | ** --clean <CSG> WARNING: Never prompt to delete any files matching |
| 682 | ** this comma separated list of glob patterns. Also, |
| 683 | ** deletions of any files matching this pattern list |
| 684 | ** cannot be undone. |
| 685 | ** --ignore <CSG> Ignore files matching patterns from the |
| 686 | ** comma separated list of glob patterns. |
| 687 | ** --keep <CSG> Keep files matching this comma separated |
| 688 | ** list of glob patterns. |
| 689 | ** -n|--dry-run Delete nothing, but display what would have been |
| @@ -685,23 +694,30 @@ | |
| 694 | ** See also: addremove, extras, status |
| 695 | */ |
| 696 | void clean_cmd(void){ |
| 697 | int allFileFlag, allDirFlag, dryRunFlag, verboseFlag; |
| 698 | int emptyDirsFlag, dirsOnlyFlag; |
| 699 | int disableUndo; |
| 700 | unsigned scanFlags = 0; |
| 701 | int verilyFlag = 0; |
| 702 | const char *zIgnoreFlag, *zKeepFlag, *zCleanFlag; |
| 703 | Glob *pIgnore, *pKeep, *pClean; |
| 704 | int nRoot; |
| 705 | |
| 706 | #ifndef UNDO_SIZE_LIMIT /* TODO: Setting? */ |
| 707 | #define UNDO_SIZE_LIMIT (10*1024*1024) /* 10MiB */ |
| 708 | #endif |
| 709 | |
| 710 | undo_capture_command_line(); |
| 711 | dryRunFlag = find_option("dry-run","n",0)!=0; |
| 712 | if( !dryRunFlag ){ |
| 713 | dryRunFlag = find_option("test",0,0)!=0; /* deprecated */ |
| 714 | } |
| 715 | if( !dryRunFlag ){ |
| 716 | dryRunFlag = find_option("whatif",0,0)!=0; |
| 717 | } |
| 718 | disableUndo = find_option("disable-undo",0,0)!=0; |
| 719 | allFileFlag = allDirFlag = find_option("force","f",0)!=0; |
| 720 | dirsOnlyFlag = find_option("dirsonly",0,0)!=0; |
| 721 | emptyDirsFlag = find_option("emptydirs","d",0)!=0 || dirsOnlyFlag; |
| 722 | if( find_option("dotfiles",0,0)!=0 ) scanFlags |= SCAN_ALL; |
| 723 | if( find_option("temp",0,0)!=0 ) scanFlags |= SCAN_TEMP; |
| @@ -734,10 +750,11 @@ | |
| 750 | nRoot = (int)strlen(g.zLocalRoot); |
| 751 | g.allowSymlinks = 1; /* Find symlinks too */ |
| 752 | if( !dirsOnlyFlag ){ |
| 753 | Stmt q; |
| 754 | Blob repo; |
| 755 | if( !dryRunFlag && !disableUndo ) undo_begin(); |
| 756 | locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore, 0); |
| 757 | db_prepare(&q, |
| 758 | "SELECT %Q || x FROM sfile" |
| 759 | " WHERE x NOT IN (%s)" |
| 760 | " ORDER BY 1", |
| @@ -755,23 +772,32 @@ | |
| 772 | " or \"keep-glob\")\n", zName+nRoot); |
| 773 | } |
| 774 | continue; |
| 775 | } |
| 776 | if( !allFileFlag && !dryRunFlag && !glob_match(pClean, zName+nRoot) ){ |
| 777 | int undoRc = UNDO_NONE; |
| 778 | if( !disableUndo ){ |
| 779 | undoRc = undo_maybe_save(zName+nRoot, UNDO_SIZE_LIMIT); |
| 780 | } |
| 781 | if( undoRc!=UNDO_SAVED_OK ){ |
| 782 | Blob ans; |
| 783 | char cReply; |
| 784 | char *prompt = mprintf("\nWARNING: Deletion of this file will " |
| 785 | "not be undoable via the 'undo'\n" |
| 786 | " command because %s.\n\n" |
| 787 | "Remove unmanaged file \"%s\" (a=all/y/N)? ", |
| 788 | undo_save_message(undoRc), zName+nRoot); |
| 789 | prompt_user(prompt, &ans); |
| 790 | cReply = blob_str(&ans)[0]; |
| 791 | if( cReply=='a' || cReply=='A' ){ |
| 792 | allFileFlag = 1; |
| 793 | }else if( cReply!='y' && cReply!='Y' ){ |
| 794 | blob_reset(&ans); |
| 795 | continue; |
| 796 | } |
| 797 | blob_reset(&ans); |
| 798 | } |
| 799 | } |
| 800 | if( dryRunFlag || file_delete(zName)==0 ){ |
| 801 | if( verboseFlag || dryRunFlag ){ |
| 802 | fossil_print("Removed unmanaged file: %s\n", zName+nRoot); |
| 803 | } |
| @@ -778,10 +804,11 @@ | |
| 804 | }else if( verboseFlag ){ |
| 805 | fossil_print("Could not remove file: %s\n", zName+nRoot); |
| 806 | } |
| 807 | } |
| 808 | db_finalize(&q); |
| 809 | if( !dryRunFlag && !disableUndo ) undo_finish(); |
| 810 | } |
| 811 | if( emptyDirsFlag ){ |
| 812 | Glob *pEmptyDirs = glob_create(db_get("empty-dirs", 0)); |
| 813 | Stmt q; |
| 814 | Blob root; |
| 815 |
+25
-4
| --- src/undo.c | ||
| +++ src/undo.c | ||
| @@ -20,15 +20,16 @@ | ||
| 20 | 20 | #include "config.h" |
| 21 | 21 | #include "undo.h" |
| 22 | 22 | |
| 23 | 23 | #if INTERFACE |
| 24 | 24 | /* |
| 25 | -** Return values from the undo_maybe_save() routine. | |
| 25 | +** Possible return values from the undo_maybe_save() routine. | |
| 26 | 26 | */ |
| 27 | -#define UNDO_SAVED_OK (0) /* The specified file was saved succesfully. */ | |
| 28 | -#define UNDO_INACTIVE (1) /* File not saved, subsystem is not active. */ | |
| 29 | -#define UNDO_TOOBIG (2) /* File not saved, it exceeded a size limit. */ | |
| 27 | +#define UNDO_NONE (0) /* Placeholder only used to initialize vars. */ | |
| 28 | +#define UNDO_SAVED_OK (1) /* The specified file was saved succesfully. */ | |
| 29 | +#define UNDO_INACTIVE (2) /* File not saved, subsystem is not active. */ | |
| 30 | +#define UNDO_TOOBIG (3) /* File not saved, it exceeded a size limit. */ | |
| 30 | 31 | #endif |
| 31 | 32 | |
| 32 | 33 | /* |
| 33 | 34 | ** Undo the change to the file zPathname. zPathname is the pathname |
| 34 | 35 | ** of the file relative to the root of the repository. If redoFlag is |
| @@ -342,10 +343,30 @@ | ||
| 342 | 343 | result = UNDO_TOOBIG; |
| 343 | 344 | } |
| 344 | 345 | free(zFullname); |
| 345 | 346 | return result; |
| 346 | 347 | } |
| 348 | + | |
| 349 | +/* | |
| 350 | +** Returns an error message for the undo_maybe_save() return code. | |
| 351 | +** Currently, this function assumes that the caller is using the | |
| 352 | +** returned error message in a context prefixed with "because". | |
| 353 | +*/ | |
| 354 | +const char *undo_save_message(int rc){ | |
| 355 | + static char zRc[32]; | |
| 356 | + | |
| 357 | + switch( rc ){ | |
| 358 | + case UNDO_NONE: return "undo is disabled for this operation"; | |
| 359 | + case UNDO_SAVED_OK: return "the save operation was successful"; | |
| 360 | + case UNDO_INACTIVE: return "the undo subsystem is inactive"; | |
| 361 | + case UNDO_TOOBIG: return "the file is too big"; | |
| 362 | + default: { | |
| 363 | + sqlite3_snprintf(sizeof(zRc), zRc, "of error code %d", rc); | |
| 364 | + } | |
| 365 | + } | |
| 366 | + return zRc; | |
| 367 | +} | |
| 347 | 368 | |
| 348 | 369 | /* |
| 349 | 370 | ** Make the current state of stashid undoable. |
| 350 | 371 | */ |
| 351 | 372 | void undo_save_stash(int stashid){ |
| 352 | 373 |
| --- src/undo.c | |
| +++ src/undo.c | |
| @@ -20,15 +20,16 @@ | |
| 20 | #include "config.h" |
| 21 | #include "undo.h" |
| 22 | |
| 23 | #if INTERFACE |
| 24 | /* |
| 25 | ** Return values from the undo_maybe_save() routine. |
| 26 | */ |
| 27 | #define UNDO_SAVED_OK (0) /* The specified file was saved succesfully. */ |
| 28 | #define UNDO_INACTIVE (1) /* File not saved, subsystem is not active. */ |
| 29 | #define UNDO_TOOBIG (2) /* File not saved, it exceeded a size limit. */ |
| 30 | #endif |
| 31 | |
| 32 | /* |
| 33 | ** Undo the change to the file zPathname. zPathname is the pathname |
| 34 | ** of the file relative to the root of the repository. If redoFlag is |
| @@ -342,10 +343,30 @@ | |
| 342 | result = UNDO_TOOBIG; |
| 343 | } |
| 344 | free(zFullname); |
| 345 | return result; |
| 346 | } |
| 347 | |
| 348 | /* |
| 349 | ** Make the current state of stashid undoable. |
| 350 | */ |
| 351 | void undo_save_stash(int stashid){ |
| 352 |
| --- src/undo.c | |
| +++ src/undo.c | |
| @@ -20,15 +20,16 @@ | |
| 20 | #include "config.h" |
| 21 | #include "undo.h" |
| 22 | |
| 23 | #if INTERFACE |
| 24 | /* |
| 25 | ** Possible return values from the undo_maybe_save() routine. |
| 26 | */ |
| 27 | #define UNDO_NONE (0) /* Placeholder only used to initialize vars. */ |
| 28 | #define UNDO_SAVED_OK (1) /* The specified file was saved succesfully. */ |
| 29 | #define UNDO_INACTIVE (2) /* File not saved, subsystem is not active. */ |
| 30 | #define UNDO_TOOBIG (3) /* File not saved, it exceeded a size limit. */ |
| 31 | #endif |
| 32 | |
| 33 | /* |
| 34 | ** Undo the change to the file zPathname. zPathname is the pathname |
| 35 | ** of the file relative to the root of the repository. If redoFlag is |
| @@ -342,10 +343,30 @@ | |
| 343 | result = UNDO_TOOBIG; |
| 344 | } |
| 345 | free(zFullname); |
| 346 | return result; |
| 347 | } |
| 348 | |
| 349 | /* |
| 350 | ** Returns an error message for the undo_maybe_save() return code. |
| 351 | ** Currently, this function assumes that the caller is using the |
| 352 | ** returned error message in a context prefixed with "because". |
| 353 | */ |
| 354 | const char *undo_save_message(int rc){ |
| 355 | static char zRc[32]; |
| 356 | |
| 357 | switch( rc ){ |
| 358 | case UNDO_NONE: return "undo is disabled for this operation"; |
| 359 | case UNDO_SAVED_OK: return "the save operation was successful"; |
| 360 | case UNDO_INACTIVE: return "the undo subsystem is inactive"; |
| 361 | case UNDO_TOOBIG: return "the file is too big"; |
| 362 | default: { |
| 363 | sqlite3_snprintf(sizeof(zRc), zRc, "of error code %d", rc); |
| 364 | } |
| 365 | } |
| 366 | return zRc; |
| 367 | } |
| 368 | |
| 369 | /* |
| 370 | ** Make the current state of stashid undoable. |
| 371 | */ |
| 372 | void undo_save_stash(int stashid){ |
| 373 |