Fossil SCM

Make the "fossil clean" command undoable.

drh 2015-07-14 00:38 trunk merge
Commit 1bf792eeeb4171f722bd18a773f559e5facabf03
--- src/allrepo.c
+++ src/allrepo.c
@@ -196,15 +196,17 @@
196196
zCmd = "clean --chdir";
197197
collect_argument(&extra, "allckouts",0);
198198
collect_argument_value(&extra, "case-sensitive");
199199
collect_argument_value(&extra, "clean");
200200
collect_argument(&extra, "dirsonly",0);
201
+ collect_argument(&extra, "disable-undo",0);
201202
collect_argument(&extra, "dotfiles",0);
202203
collect_argument(&extra, "emptydirs",0);
203204
collect_argument(&extra, "force","f");
204205
collect_argument_value(&extra, "ignore");
205206
collect_argument_value(&extra, "keep");
207
+ collect_argument(&extra, "no-prompt",0);
206208
collect_argument(&extra, "temp",0);
207209
collect_argument(&extra, "verbose","v");
208210
collect_argument(&extra, "whatif",0);
209211
useCheckouts = 1;
210212
}else if( strncmp(zCmd, "dbstat", n)==0 ){
211213
--- src/allrepo.c
+++ src/allrepo.c
@@ -196,15 +196,17 @@
196 zCmd = "clean --chdir";
197 collect_argument(&extra, "allckouts",0);
198 collect_argument_value(&extra, "case-sensitive");
199 collect_argument_value(&extra, "clean");
200 collect_argument(&extra, "dirsonly",0);
 
201 collect_argument(&extra, "dotfiles",0);
202 collect_argument(&extra, "emptydirs",0);
203 collect_argument(&extra, "force","f");
204 collect_argument_value(&extra, "ignore");
205 collect_argument_value(&extra, "keep");
 
206 collect_argument(&extra, "temp",0);
207 collect_argument(&extra, "verbose","v");
208 collect_argument(&extra, "whatif",0);
209 useCheckouts = 1;
210 }else if( strncmp(zCmd, "dbstat", n)==0 ){
211
--- src/allrepo.c
+++ src/allrepo.c
@@ -196,15 +196,17 @@
196 zCmd = "clean --chdir";
197 collect_argument(&extra, "allckouts",0);
198 collect_argument_value(&extra, "case-sensitive");
199 collect_argument_value(&extra, "clean");
200 collect_argument(&extra, "dirsonly",0);
201 collect_argument(&extra, "disable-undo",0);
202 collect_argument(&extra, "dotfiles",0);
203 collect_argument(&extra, "emptydirs",0);
204 collect_argument(&extra, "force","f");
205 collect_argument_value(&extra, "ignore");
206 collect_argument_value(&extra, "keep");
207 collect_argument(&extra, "no-prompt",0);
208 collect_argument(&extra, "temp",0);
209 collect_argument(&extra, "verbose","v");
210 collect_argument(&extra, "whatif",0);
211 useCheckouts = 1;
212 }else if( strncmp(zCmd, "dbstat", n)==0 ){
213
+67 -27
--- src/checkin.c
+++ src/checkin.c
@@ -644,11 +644,12 @@
644644
** Files and subdirectories whose names begin with "." are automatically
645645
** ignored unless the --dotfiles option is used.
646646
**
647647
** The --verily option ignores the keep-glob and ignore-glob settings
648648
** 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.
650651
**
651652
** Options:
652653
** --allckouts Check for empty directories within any checkouts
653654
** that may be nested within the current one. This
654655
** option should be used with great care because the
@@ -657,51 +658,70 @@
657658
** not be checked.
658659
** --case-sensitive <BOOL> override case-sensitive setting
659660
** --dirsonly Only remove empty directories. No files will
660661
** be removed. Using this option will automatically
661662
** 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.
662666
** --dotfiles Include files beginning with a dot (".").
663667
** --emptydirs Remove any empty directories that are not
664668
** explicitly exempted via the empty-dirs setting
665669
** or another applicable setting or command line
666670
** argument. Matching files, if any, are removed
667671
** prior to checking for any empty directories;
668672
** therefore, directories that contain only files
669673
** that were removed will be removed as well.
670674
** -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: Removes everything that is not a managed
676
+** file or the repository itself. This option
677
+** implies the --force, --emptydirs, --dotfiles, and
678
+** --disable-undo options. Furthermore, it completely
679
+** disregards the keep-glob and ignore-glob settings.
680
+** However, it does honor the --ignore and --keep
681
+** options.
682
+** --clean <CSG> WARNING: Never prompt to delete any files matching
683
+** this comma separated list of glob patterns. Also,
684
+** deletions of any files matching this pattern list
685
+** cannot be undone.
676686
** --ignore <CSG> Ignore files matching patterns from the
677687
** comma separated list of glob patterns.
678688
** --keep <CSG> Keep files matching this comma separated
679689
** list of glob patterns.
680690
** -n|--dry-run Delete nothing, but display what would have been
681691
** deleted.
692
+** --no-prompt This option disables prompting the user for input
693
+** and assumes an answer of 'No' for every question.
682694
** --temp Remove only Fossil-generated temporary files.
683695
** -v|--verbose Show all files as they are removed.
684696
**
685697
** See also: addremove, extras, status
686698
*/
687699
void clean_cmd(void){
688700
int allFileFlag, allDirFlag, dryRunFlag, verboseFlag;
689701
int emptyDirsFlag, dirsOnlyFlag;
702
+ int disableUndo, noPrompt;
690703
unsigned scanFlags = 0;
691704
int verilyFlag = 0;
692705
const char *zIgnoreFlag, *zKeepFlag, *zCleanFlag;
693706
Glob *pIgnore, *pKeep, *pClean;
694707
int nRoot;
695708
709
+#ifndef UNDO_SIZE_LIMIT /* TODO: Setting? */
710
+#define UNDO_SIZE_LIMIT (10*1024*1024) /* 10MiB */
711
+#endif
712
+
713
+ undo_capture_command_line();
696714
dryRunFlag = find_option("dry-run","n",0)!=0;
697715
if( !dryRunFlag ){
698716
dryRunFlag = find_option("test",0,0)!=0; /* deprecated */
699717
}
700718
if( !dryRunFlag ){
701719
dryRunFlag = find_option("whatif",0,0)!=0;
702720
}
721
+ disableUndo = find_option("disable-undo",0,0)!=0;
722
+ noPrompt = find_option("no-prompt",0,0)!=0;
703723
allFileFlag = allDirFlag = find_option("force","f",0)!=0;
704724
dirsOnlyFlag = find_option("dirsonly",0,0)!=0;
705725
emptyDirsFlag = find_option("emptydirs","d",0)!=0 || dirsOnlyFlag;
706726
if( find_option("dotfiles",0,0)!=0 ) scanFlags |= SCAN_ALL;
707727
if( find_option("temp",0,0)!=0 ) scanFlags |= SCAN_TEMP;
@@ -712,10 +732,11 @@
712732
zCleanFlag = find_option("clean",0,1);
713733
db_must_be_within_tree();
714734
if( find_option("verily","x",0)!=0 ){
715735
verilyFlag = allFileFlag = allDirFlag = 1;
716736
emptyDirsFlag = 1;
737
+ disableUndo = 1;
717738
scanFlags |= SCAN_ALL;
718739
zCleanFlag = 0;
719740
}
720741
if( zIgnoreFlag==0 && !verilyFlag ){
721742
zIgnoreFlag = db_get("ignore-glob", 0);
@@ -734,10 +755,11 @@
734755
nRoot = (int)strlen(g.zLocalRoot);
735756
g.allowSymlinks = 1; /* Find symlinks too */
736757
if( !dirsOnlyFlag ){
737758
Stmt q;
738759
Blob repo;
760
+ if( !dryRunFlag && !disableUndo ) undo_begin();
739761
locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore, 0);
740762
db_prepare(&q,
741763
"SELECT %Q || x FROM sfile"
742764
" WHERE x NOT IN (%s)"
743765
" ORDER BY 1",
@@ -754,24 +776,38 @@
754776
fossil_print("KEPT file \"%s\" not removed (due to --keep"
755777
" or \"keep-glob\")\n", zName+nRoot);
756778
}
757779
continue;
758780
}
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);
781
+ if( !dryRunFlag && !glob_match(pClean, zName+nRoot) ){
782
+ int undoRc = UNDO_NONE;
783
+ if( !disableUndo ){
784
+ undoRc = undo_maybe_save(zName+nRoot, UNDO_SIZE_LIMIT);
785
+ }
786
+ if( undoRc!=UNDO_SAVED_OK ){
787
+ char cReply;
788
+ if( allFileFlag ){
789
+ cReply = 'Y';
790
+ }else if( !noPrompt ){
791
+ Blob ans;
792
+ char *prompt = mprintf("\nWARNING: Deletion of this file will "
793
+ "not be undoable via the 'undo'\n"
794
+ " command because %s.\n\n"
795
+ "Remove unmanaged file \"%s\" (a=all/y/N)? ",
796
+ undo_save_message(undoRc), zName+nRoot);
797
+ prompt_user(prompt, &ans);
798
+ cReply = blob_str(&ans)[0];
799
+ blob_reset(&ans);
800
+ }else{
801
+ cReply = 'N';
802
+ }
803
+ if( cReply=='a' || cReply=='A' ){
804
+ allFileFlag = 1;
805
+ }else if( cReply!='y' && cReply!='Y' ){
806
+ continue;
807
+ }
808
+ }
773809
}
774810
if( dryRunFlag || file_delete(zName)==0 ){
775811
if( verboseFlag || dryRunFlag ){
776812
fossil_print("Removed unmanaged file: %s\n", zName+nRoot);
777813
}
@@ -778,10 +814,11 @@
778814
}else if( verboseFlag ){
779815
fossil_print("Could not remove file: %s\n", zName+nRoot);
780816
}
781817
}
782818
db_finalize(&q);
819
+ if( !dryRunFlag && !disableUndo ) undo_finish();
783820
}
784821
if( emptyDirsFlag ){
785822
Glob *pEmptyDirs = glob_create(db_get("empty-dirs", 0));
786823
Stmt q;
787824
Blob root;
@@ -803,23 +840,26 @@
803840
" or \"keep-glob\")\n", zName+nRoot);
804841
}
805842
continue;
806843
}
807844
if( !allDirFlag && !dryRunFlag && !glob_match(pClean, zName+nRoot) ){
808
- Blob ans;
809845
char cReply;
810
- char *prompt = mprintf("Remove empty directory \"%s\" (a=all/y/N)? ",
811
- zName+nRoot);
812
- prompt_user(prompt, &ans);
813
- cReply = blob_str(&ans)[0];
846
+ if( !noPrompt ){
847
+ Blob ans;
848
+ char *prompt = mprintf("Remove empty directory \"%s\" (a=all/y/N)? ",
849
+ zName+nRoot);
850
+ prompt_user(prompt, &ans);
851
+ cReply = blob_str(&ans)[0];
852
+ blob_reset(&ans);
853
+ }else{
854
+ cReply = 'N';
855
+ }
814856
if( cReply=='a' || cReply=='A' ){
815857
allDirFlag = 1;
816858
}else if( cReply!='y' && cReply!='Y' ){
817
- blob_reset(&ans);
818859
continue;
819860
}
820
- blob_reset(&ans);
821861
}
822862
if( dryRunFlag || file_rmdir(zName)==0 ){
823863
if( verboseFlag || dryRunFlag ){
824864
fossil_print("Removed unmanaged directory: %s\n", zName+nRoot);
825865
}
826866
--- 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,51 +658,70 @@
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
681 ** deleted.
 
 
682 ** --temp Remove only Fossil-generated temporary files.
683 ** -v|--verbose Show all files as they are removed.
684 **
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;
@@ -712,10 +732,11 @@
712 zCleanFlag = find_option("clean",0,1);
713 db_must_be_within_tree();
714 if( find_option("verily","x",0)!=0 ){
715 verilyFlag = allFileFlag = allDirFlag = 1;
716 emptyDirsFlag = 1;
 
717 scanFlags |= SCAN_ALL;
718 zCleanFlag = 0;
719 }
720 if( zIgnoreFlag==0 && !verilyFlag ){
721 zIgnoreFlag = db_get("ignore-glob", 0);
@@ -734,10 +755,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",
@@ -754,24 +776,38 @@
754 fossil_print("KEPT file \"%s\" not removed (due to --keep"
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 +814,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;
@@ -803,23 +840,26 @@
803 " or \"keep-glob\")\n", zName+nRoot);
804 }
805 continue;
806 }
807 if( !allDirFlag && !dryRunFlag && !glob_match(pClean, zName+nRoot) ){
808 Blob ans;
809 char cReply;
810 char *prompt = mprintf("Remove empty directory \"%s\" (a=all/y/N)? ",
811 zName+nRoot);
812 prompt_user(prompt, &ans);
813 cReply = blob_str(&ans)[0];
 
 
 
 
 
 
814 if( cReply=='a' || cReply=='A' ){
815 allDirFlag = 1;
816 }else if( cReply!='y' && cReply!='Y' ){
817 blob_reset(&ans);
818 continue;
819 }
820 blob_reset(&ans);
821 }
822 if( dryRunFlag || file_rmdir(zName)==0 ){
823 if( verboseFlag || dryRunFlag ){
824 fossil_print("Removed unmanaged directory: %s\n", zName+nRoot);
825 }
826
--- 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,51 +658,70 @@
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: Removes everything that is not a managed
676 ** file or the repository itself. This option
677 ** implies the --force, --emptydirs, --dotfiles, and
678 ** --disable-undo options. Furthermore, it completely
679 ** disregards the keep-glob and ignore-glob settings.
680 ** However, it does honor the --ignore and --keep
681 ** options.
682 ** --clean <CSG> WARNING: Never prompt to delete any files matching
683 ** this comma separated list of glob patterns. Also,
684 ** deletions of any files matching this pattern list
685 ** cannot be undone.
686 ** --ignore <CSG> Ignore files matching patterns from the
687 ** comma separated list of glob patterns.
688 ** --keep <CSG> Keep files matching this comma separated
689 ** list of glob patterns.
690 ** -n|--dry-run Delete nothing, but display what would have been
691 ** deleted.
692 ** --no-prompt This option disables prompting the user for input
693 ** and assumes an answer of 'No' for every question.
694 ** --temp Remove only Fossil-generated temporary files.
695 ** -v|--verbose Show all files as they are removed.
696 **
697 ** See also: addremove, extras, status
698 */
699 void clean_cmd(void){
700 int allFileFlag, allDirFlag, dryRunFlag, verboseFlag;
701 int emptyDirsFlag, dirsOnlyFlag;
702 int disableUndo, noPrompt;
703 unsigned scanFlags = 0;
704 int verilyFlag = 0;
705 const char *zIgnoreFlag, *zKeepFlag, *zCleanFlag;
706 Glob *pIgnore, *pKeep, *pClean;
707 int nRoot;
708
709 #ifndef UNDO_SIZE_LIMIT /* TODO: Setting? */
710 #define UNDO_SIZE_LIMIT (10*1024*1024) /* 10MiB */
711 #endif
712
713 undo_capture_command_line();
714 dryRunFlag = find_option("dry-run","n",0)!=0;
715 if( !dryRunFlag ){
716 dryRunFlag = find_option("test",0,0)!=0; /* deprecated */
717 }
718 if( !dryRunFlag ){
719 dryRunFlag = find_option("whatif",0,0)!=0;
720 }
721 disableUndo = find_option("disable-undo",0,0)!=0;
722 noPrompt = find_option("no-prompt",0,0)!=0;
723 allFileFlag = allDirFlag = find_option("force","f",0)!=0;
724 dirsOnlyFlag = find_option("dirsonly",0,0)!=0;
725 emptyDirsFlag = find_option("emptydirs","d",0)!=0 || dirsOnlyFlag;
726 if( find_option("dotfiles",0,0)!=0 ) scanFlags |= SCAN_ALL;
727 if( find_option("temp",0,0)!=0 ) scanFlags |= SCAN_TEMP;
@@ -712,10 +732,11 @@
732 zCleanFlag = find_option("clean",0,1);
733 db_must_be_within_tree();
734 if( find_option("verily","x",0)!=0 ){
735 verilyFlag = allFileFlag = allDirFlag = 1;
736 emptyDirsFlag = 1;
737 disableUndo = 1;
738 scanFlags |= SCAN_ALL;
739 zCleanFlag = 0;
740 }
741 if( zIgnoreFlag==0 && !verilyFlag ){
742 zIgnoreFlag = db_get("ignore-glob", 0);
@@ -734,10 +755,11 @@
755 nRoot = (int)strlen(g.zLocalRoot);
756 g.allowSymlinks = 1; /* Find symlinks too */
757 if( !dirsOnlyFlag ){
758 Stmt q;
759 Blob repo;
760 if( !dryRunFlag && !disableUndo ) undo_begin();
761 locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore, 0);
762 db_prepare(&q,
763 "SELECT %Q || x FROM sfile"
764 " WHERE x NOT IN (%s)"
765 " ORDER BY 1",
@@ -754,24 +776,38 @@
776 fossil_print("KEPT file \"%s\" not removed (due to --keep"
777 " or \"keep-glob\")\n", zName+nRoot);
778 }
779 continue;
780 }
781 if( !dryRunFlag && !glob_match(pClean, zName+nRoot) ){
782 int undoRc = UNDO_NONE;
783 if( !disableUndo ){
784 undoRc = undo_maybe_save(zName+nRoot, UNDO_SIZE_LIMIT);
785 }
786 if( undoRc!=UNDO_SAVED_OK ){
787 char cReply;
788 if( allFileFlag ){
789 cReply = 'Y';
790 }else if( !noPrompt ){
791 Blob ans;
792 char *prompt = mprintf("\nWARNING: Deletion of this file will "
793 "not be undoable via the 'undo'\n"
794 " command because %s.\n\n"
795 "Remove unmanaged file \"%s\" (a=all/y/N)? ",
796 undo_save_message(undoRc), zName+nRoot);
797 prompt_user(prompt, &ans);
798 cReply = blob_str(&ans)[0];
799 blob_reset(&ans);
800 }else{
801 cReply = 'N';
802 }
803 if( cReply=='a' || cReply=='A' ){
804 allFileFlag = 1;
805 }else if( cReply!='y' && cReply!='Y' ){
806 continue;
807 }
808 }
809 }
810 if( dryRunFlag || file_delete(zName)==0 ){
811 if( verboseFlag || dryRunFlag ){
812 fossil_print("Removed unmanaged file: %s\n", zName+nRoot);
813 }
@@ -778,10 +814,11 @@
814 }else if( verboseFlag ){
815 fossil_print("Could not remove file: %s\n", zName+nRoot);
816 }
817 }
818 db_finalize(&q);
819 if( !dryRunFlag && !disableUndo ) undo_finish();
820 }
821 if( emptyDirsFlag ){
822 Glob *pEmptyDirs = glob_create(db_get("empty-dirs", 0));
823 Stmt q;
824 Blob root;
@@ -803,23 +840,26 @@
840 " or \"keep-glob\")\n", zName+nRoot);
841 }
842 continue;
843 }
844 if( !allDirFlag && !dryRunFlag && !glob_match(pClean, zName+nRoot) ){
 
845 char cReply;
846 if( !noPrompt ){
847 Blob ans;
848 char *prompt = mprintf("Remove empty directory \"%s\" (a=all/y/N)? ",
849 zName+nRoot);
850 prompt_user(prompt, &ans);
851 cReply = blob_str(&ans)[0];
852 blob_reset(&ans);
853 }else{
854 cReply = 'N';
855 }
856 if( cReply=='a' || cReply=='A' ){
857 allDirFlag = 1;
858 }else if( cReply!='y' && cReply!='Y' ){
 
859 continue;
860 }
 
861 }
862 if( dryRunFlag || file_rmdir(zName)==0 ){
863 if( verboseFlag || dryRunFlag ){
864 fossil_print("Removed unmanaged directory: %s\n", zName+nRoot);
865 }
866
+99 -26
--- src/undo.c
+++ src/undo.c
@@ -18,11 +18,19 @@
1818
** This file implements the undo/redo functionality.
1919
*/
2020
#include "config.h"
2121
#include "undo.h"
2222
23
-
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
2432
2533
/*
2634
** Undo the change to the file zPathname. zPathname is the pathname
2735
** of the file relative to the root of the repository. If redoFlag is
2836
** true the redo a change. If there is nothing to undo (or redo) then
@@ -261,41 +269,103 @@
261269
** Save the current content of the file zPathname so that it
262270
** will be undoable. The name is relative to the root of the
263271
** tree.
264272
*/
265273
void undo_save(const char *zPathname){
274
+ if( undo_maybe_save(zPathname, -1)!=UNDO_SAVED_OK ){
275
+ fossil_panic("failed to save undo information for path: %s",
276
+ zPathname);
277
+ }
278
+}
279
+
280
+/*
281
+** Possibly save the current content of the file zPathname so
282
+** that it will be undoable. The name is relative to the root
283
+** of the tree. The limit argument may be used to specify the
284
+** maximum size for the file to be saved. If the size of the
285
+** specified file exceeds this size limit (in bytes), it will
286
+** not be saved and an appropriate code will be returned.
287
+**
288
+** WARNING: Please do NOT call this function with a limit
289
+** value less than zero, call the undo_save()
290
+** function instead.
291
+**
292
+** The return value of this function will always be one of the
293
+** following codes:
294
+**
295
+** UNDO_SAVED_OK: The specified file was saved succesfully.
296
+**
297
+** UNDO_INACTIVE: The specified file was NOT saved, because the
298
+** "undo subsystem" is not active. This error
299
+** may indicate that a call to undo_begin() is
300
+** missing.
301
+**
302
+** UNDO_TOOBIG: The specified file was NOT saved, because it
303
+** exceeded the specified size limit. It is
304
+** impossible for this value to be returned if
305
+** the specified size limit is less than zero
306
+** (i.e. unlimited).
307
+*/
308
+int undo_maybe_save(const char *zPathname, i64 limit){
266309
char *zFullname;
267
- Blob content;
268
- int existsFlag;
269
- int isLink;
270
- Stmt q;
310
+ i64 size;
311
+ int result;
271312
272
- if( !undoActive ) return;
313
+ if( !undoActive ) return UNDO_INACTIVE;
273314
zFullname = mprintf("%s%s", g.zLocalRoot, zPathname);
274
- existsFlag = file_wd_size(zFullname)>=0;
275
- isLink = file_wd_islink(zFullname);
276
- db_prepare(&q,
277
- "INSERT OR IGNORE INTO"
278
- " undo(pathname,redoflag,existsflag,isExe,isLink,content)"
279
- " VALUES(%Q,0,%d,%d,%d,:c)",
280
- zPathname, existsFlag, file_wd_isexe(zFullname), isLink
281
- );
282
- if( existsFlag ){
283
- if( isLink ){
284
- blob_read_link(&content, zFullname);
285
- }else{
286
- blob_read_from_file(&content, zFullname);
287
- }
288
- db_bind_blob(&q, ":c", &content);
315
+ size = file_wd_size(zFullname);
316
+ if( limit<0 || size<=limit ){
317
+ int existsFlag = (size>=0);
318
+ int isLink = file_wd_islink(zFullname);
319
+ Stmt q;
320
+ Blob content;
321
+ db_prepare(&q,
322
+ "INSERT OR IGNORE INTO"
323
+ " undo(pathname,redoflag,existsflag,isExe,isLink,content)"
324
+ " VALUES(%Q,0,%d,%d,%d,:c)",
325
+ zPathname, existsFlag, file_wd_isexe(zFullname), isLink
326
+ );
327
+ if( existsFlag ){
328
+ if( isLink ){
329
+ blob_read_link(&content, zFullname);
330
+ }else{
331
+ blob_read_from_file(&content, zFullname);
332
+ }
333
+ db_bind_blob(&q, ":c", &content);
334
+ }
335
+ db_step(&q);
336
+ db_finalize(&q);
337
+ if( existsFlag ){
338
+ blob_reset(&content);
339
+ }
340
+ undoNeedRollback = 1;
341
+ result = UNDO_SAVED_OK;
342
+ }else{
343
+ result = UNDO_TOOBIG;
289344
}
290345
free(zFullname);
291
- db_step(&q);
292
- db_finalize(&q);
293
- if( existsFlag ){
294
- blob_reset(&content);
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
+ }
295365
}
296
- undoNeedRollback = 1;
366
+ return zRc;
297367
}
298368
299369
/*
300370
** Make the current state of stashid undoable.
301371
*/
@@ -361,10 +431,13 @@
361431
**
362432
** (1) fossil update (5) fossil stash apply
363433
** (2) fossil merge (6) fossil stash drop
364434
** (3) fossil revert (7) fossil stash goto
365435
** (4) fossil stash pop
436
+**
437
+** The "fossil clean" operation can also be undone; however, this is
438
+** currently limited to files that are less than 10MiB in size.
366439
**
367440
** If FILENAME is specified then restore the content of the named
368441
** file(s) but otherwise leave the update or merge or revert in effect.
369442
** The redo command undoes the effect of the most recent undo.
370443
**
371444
372445
ADDED test/clean.test
--- src/undo.c
+++ src/undo.c
@@ -18,11 +18,19 @@
18 ** This file implements the undo/redo functionality.
19 */
20 #include "config.h"
21 #include "undo.h"
22
23
 
 
 
 
 
 
 
 
24
25 /*
26 ** Undo the change to the file zPathname. zPathname is the pathname
27 ** of the file relative to the root of the repository. If redoFlag is
28 ** true the redo a change. If there is nothing to undo (or redo) then
@@ -261,41 +269,103 @@
261 ** Save the current content of the file zPathname so that it
262 ** will be undoable. The name is relative to the root of the
263 ** tree.
264 */
265 void undo_save(const char *zPathname){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
266 char *zFullname;
267 Blob content;
268 int existsFlag;
269 int isLink;
270 Stmt q;
271
272 if( !undoActive ) return;
273 zFullname = mprintf("%s%s", g.zLocalRoot, zPathname);
274 existsFlag = file_wd_size(zFullname)>=0;
275 isLink = file_wd_islink(zFullname);
276 db_prepare(&q,
277 "INSERT OR IGNORE INTO"
278 " undo(pathname,redoflag,existsflag,isExe,isLink,content)"
279 " VALUES(%Q,0,%d,%d,%d,:c)",
280 zPathname, existsFlag, file_wd_isexe(zFullname), isLink
281 );
282 if( existsFlag ){
283 if( isLink ){
284 blob_read_link(&content, zFullname);
285 }else{
286 blob_read_from_file(&content, zFullname);
287 }
288 db_bind_blob(&q, ":c", &content);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
289 }
290 free(zFullname);
291 db_step(&q);
292 db_finalize(&q);
293 if( existsFlag ){
294 blob_reset(&content);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
295 }
296 undoNeedRollback = 1;
297 }
298
299 /*
300 ** Make the current state of stashid undoable.
301 */
@@ -361,10 +431,13 @@
361 **
362 ** (1) fossil update (5) fossil stash apply
363 ** (2) fossil merge (6) fossil stash drop
364 ** (3) fossil revert (7) fossil stash goto
365 ** (4) fossil stash pop
 
 
 
366 **
367 ** If FILENAME is specified then restore the content of the named
368 ** file(s) but otherwise leave the update or merge or revert in effect.
369 ** The redo command undoes the effect of the most recent undo.
370 **
371
372 DDED test/clean.test
--- src/undo.c
+++ src/undo.c
@@ -18,11 +18,19 @@
18 ** This file implements the undo/redo functionality.
19 */
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
36 ** true the redo a change. If there is nothing to undo (or redo) then
@@ -261,41 +269,103 @@
269 ** Save the current content of the file zPathname so that it
270 ** will be undoable. The name is relative to the root of the
271 ** tree.
272 */
273 void undo_save(const char *zPathname){
274 if( undo_maybe_save(zPathname, -1)!=UNDO_SAVED_OK ){
275 fossil_panic("failed to save undo information for path: %s",
276 zPathname);
277 }
278 }
279
280 /*
281 ** Possibly save the current content of the file zPathname so
282 ** that it will be undoable. The name is relative to the root
283 ** of the tree. The limit argument may be used to specify the
284 ** maximum size for the file to be saved. If the size of the
285 ** specified file exceeds this size limit (in bytes), it will
286 ** not be saved and an appropriate code will be returned.
287 **
288 ** WARNING: Please do NOT call this function with a limit
289 ** value less than zero, call the undo_save()
290 ** function instead.
291 **
292 ** The return value of this function will always be one of the
293 ** following codes:
294 **
295 ** UNDO_SAVED_OK: The specified file was saved succesfully.
296 **
297 ** UNDO_INACTIVE: The specified file was NOT saved, because the
298 ** "undo subsystem" is not active. This error
299 ** may indicate that a call to undo_begin() is
300 ** missing.
301 **
302 ** UNDO_TOOBIG: The specified file was NOT saved, because it
303 ** exceeded the specified size limit. It is
304 ** impossible for this value to be returned if
305 ** the specified size limit is less than zero
306 ** (i.e. unlimited).
307 */
308 int undo_maybe_save(const char *zPathname, i64 limit){
309 char *zFullname;
310 i64 size;
311 int result;
 
 
312
313 if( !undoActive ) return UNDO_INACTIVE;
314 zFullname = mprintf("%s%s", g.zLocalRoot, zPathname);
315 size = file_wd_size(zFullname);
316 if( limit<0 || size<=limit ){
317 int existsFlag = (size>=0);
318 int isLink = file_wd_islink(zFullname);
319 Stmt q;
320 Blob content;
321 db_prepare(&q,
322 "INSERT OR IGNORE INTO"
323 " undo(pathname,redoflag,existsflag,isExe,isLink,content)"
324 " VALUES(%Q,0,%d,%d,%d,:c)",
325 zPathname, existsFlag, file_wd_isexe(zFullname), isLink
326 );
327 if( existsFlag ){
328 if( isLink ){
329 blob_read_link(&content, zFullname);
330 }else{
331 blob_read_from_file(&content, zFullname);
332 }
333 db_bind_blob(&q, ":c", &content);
334 }
335 db_step(&q);
336 db_finalize(&q);
337 if( existsFlag ){
338 blob_reset(&content);
339 }
340 undoNeedRollback = 1;
341 result = UNDO_SAVED_OK;
342 }else{
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 */
@@ -361,10 +431,13 @@
431 **
432 ** (1) fossil update (5) fossil stash apply
433 ** (2) fossil merge (6) fossil stash drop
434 ** (3) fossil revert (7) fossil stash goto
435 ** (4) fossil stash pop
436 **
437 ** The "fossil clean" operation can also be undone; however, this is
438 ** currently limited to files that are less than 10MiB in size.
439 **
440 ** If FILENAME is specified then restore the content of the named
441 ** file(s) but otherwise leave the update or merge or revert in effect.
442 ** The redo command undoes the effect of the most recent undo.
443 **
444
445 DDED test/clean.test
--- a/test/clean.test
+++ b/test/clean.test
@@ -0,0 +1,157 @@
1
+#
2
+# Copyright (c) 2015 D. Richard Hipp
3
+#
4
+# This program is free software; you can redistribute it and/or
5
+# modify it under the terms of the Simplified BSD License (also
6
+# known as the "2-Clause License" or "FreeBSD License".)
7
+#
8
+# This program is distributed in the hope that it will be useful,
9
+# but without any warranty; without even the implied warranty of
10
+# merchantability or fitness for a particular purpose.
11
+#
12
+# Author contact information:
13
+# [email protected]
14
+# http://www.hwaci.com/drh/
15
+#
16
+############################################################################
17
+#
18
+# Tests of the "clean" command, including the ability to undo it.
19
+#
20
+
21
+repo_init###########
22
+
23
+fossil extra
24
+test clean-0 {[normalize_result] eq {}}
25
+
26
+#############0bute it and/or
27
+# modify it under the terms of the Simplified BSD License (also
28
+# kn#
29
+# Copyright (c) 2015 D. Richard Hipp
30
+#
31
+# This program is free software; you can redistribute it and/or
32
+# modify it under the terms of the Simplified BSD License (also
33
+# known as the "2-Clause License" or "FreeBSD License".)
34
+#
35
+# This program is distributed in the hope that it will be useful,
36
+# but without any warranty; without even the implied warranty of
37
+# merchantability or fitness for a particular purpose.
38
+#
39
+# Author contact information:
40
+# [email protected]
41
+# http://www.hwaci.com/drh/
42
+#
43
+############################################################################
44
+#
45
+# Tests of the "clean" command, including the ability to undo it.
46
+#
47
+
48
+test_setup
49
+
50
+###############################################################################
51
+
52
+fossil extra
53
+test clean-0 {[normalize_result] eq {}}
54
+
55
+###############################################################################
56
+
57
+write_file f1 "f1 line"
58
+fossil add f1
59
+fossil comq {NEW f2}}
60
+te3q {NEW f2}}
61
+test clean-7 {[r####################
62
+
63
+fossil extra
64
+test clean-2 {[normalize_result] eq {}}
65
+
66
+###############################################################################
67
+
68
+write_file f2 "f2 line"
69
+fossil extra
70
+test clean-3 {[normalize_result] eq {f2}}
71
+
72
+###############################################################################
73
+
74
+# clean w/undo enabled, should not prompt, 1 file < 10MiB
75
+fossil clean
76
+test clean-4 {[normalize_result] eq \
77
+{"fossil undo" is available to undo changes to the working checkout.}}
78
+
79
+###############################################################################
80
+
81
+fossil extra
82
+test clean-5 {[normalize_result] eq {}}
83
+
84
+###############################################################################
85
+
86
+fossil undo
87
+testq {NEW f2}}
88
+test clean-7 {[read_file f2] eq "f2 line"}
89
+
90
+###############################################################################
91
+
92
+fossil extra
93
+test clean-8 {[normalize_result] eq {f2}}
94
+
95
+###############################################################################
96
+
97
+write_file f3 [string repeat ABCDEFGHIJK 1048576]
98
+fossil extra
99
+test clean-9 {[normalize_result] eq {f2
100
+f3}}
101
+
102
+###############################################################################
103
+
104
+# clean w/undo enabled, no prompt, 1 file < 10MiB, 1 file > 10MiB
105
+fossil clean --no-prompt
106
+test clean-10 {[normalize_result] eq \
107
+{"fossil undo" is available to undo changes to the working checkout.}}
108
+
109
+####################################
110
+
111
+fossil undo -expectError
112
+test clean-23 {[normalize_result] eq {nothing to undo}}
113
+
114
+###############################################################################
115
+
116
+# clean w/undo disabled, force, 1 file < 10MiB, 1 file > 10MiB
117
+fossil clean --disable-undo --force
118
+test clean-24 {[normalize_result] eq {}}
119
+
120
+###############################################################################
121
+
122
+fossil extra
123
+test clean-25 {[normalize_result] eq {}}
124
+
125
+######################################
126
+test clean-26 {[normalize_result] eq {nothing to undo}}
127
+
128
+###############################################################################
129
+
130
+write_file f5 "f5 line"
131
+fossil extra
132
+test clean-27 {[normalize_result] eq {f5}}
133
+
134
+###############################################################################
135
+
136
+# clean w/undo disabled, should prompt, 1 file < 10MiB
137
+fossil_maybe_answer Y clean --disable-undo
138
+test clean-28 {[normalize_result] eq \
139
+{WARNING: Deletion of this file will not be undoable via the 'undo'
140
+ command because undo is disabled for this operation.
141
+
142
+Remove unmanaged file "f5" (a=all/y/N)?}}
143
+
144
+###############################################################################
145
+
146
+fossil extra
147
+test clean-29 {[normalize_result] eq {}}
148
+
149
+###############################################################################
150
+
151
+fossil undo
152
+test clean-30 {[normalize_result] eq {nothing to undo}}
153
+
154
+###############################################################################
155
+
156
+fossil extra
157
+test clean-31 {[normalize_result] eq {}}
--- a/test/clean.test
+++ b/test/clean.test
@@ -0,0 +1,157 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/test/clean.test
+++ b/test/clean.test
@@ -0,0 +1,157 @@
1 #
2 # Copyright (c) 2015 D. Richard Hipp
3 #
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the Simplified BSD License (also
6 # known as the "2-Clause License" or "FreeBSD License".)
7 #
8 # This program is distributed in the hope that it will be useful,
9 # but without any warranty; without even the implied warranty of
10 # merchantability or fitness for a particular purpose.
11 #
12 # Author contact information:
13 # [email protected]
14 # http://www.hwaci.com/drh/
15 #
16 ############################################################################
17 #
18 # Tests of the "clean" command, including the ability to undo it.
19 #
20
21 repo_init###########
22
23 fossil extra
24 test clean-0 {[normalize_result] eq {}}
25
26 #############0bute it and/or
27 # modify it under the terms of the Simplified BSD License (also
28 # kn#
29 # Copyright (c) 2015 D. Richard Hipp
30 #
31 # This program is free software; you can redistribute it and/or
32 # modify it under the terms of the Simplified BSD License (also
33 # known as the "2-Clause License" or "FreeBSD License".)
34 #
35 # This program is distributed in the hope that it will be useful,
36 # but without any warranty; without even the implied warranty of
37 # merchantability or fitness for a particular purpose.
38 #
39 # Author contact information:
40 # [email protected]
41 # http://www.hwaci.com/drh/
42 #
43 ############################################################################
44 #
45 # Tests of the "clean" command, including the ability to undo it.
46 #
47
48 test_setup
49
50 ###############################################################################
51
52 fossil extra
53 test clean-0 {[normalize_result] eq {}}
54
55 ###############################################################################
56
57 write_file f1 "f1 line"
58 fossil add f1
59 fossil comq {NEW f2}}
60 te3q {NEW f2}}
61 test clean-7 {[r####################
62
63 fossil extra
64 test clean-2 {[normalize_result] eq {}}
65
66 ###############################################################################
67
68 write_file f2 "f2 line"
69 fossil extra
70 test clean-3 {[normalize_result] eq {f2}}
71
72 ###############################################################################
73
74 # clean w/undo enabled, should not prompt, 1 file < 10MiB
75 fossil clean
76 test clean-4 {[normalize_result] eq \
77 {"fossil undo" is available to undo changes to the working checkout.}}
78
79 ###############################################################################
80
81 fossil extra
82 test clean-5 {[normalize_result] eq {}}
83
84 ###############################################################################
85
86 fossil undo
87 testq {NEW f2}}
88 test clean-7 {[read_file f2] eq "f2 line"}
89
90 ###############################################################################
91
92 fossil extra
93 test clean-8 {[normalize_result] eq {f2}}
94
95 ###############################################################################
96
97 write_file f3 [string repeat ABCDEFGHIJK 1048576]
98 fossil extra
99 test clean-9 {[normalize_result] eq {f2
100 f3}}
101
102 ###############################################################################
103
104 # clean w/undo enabled, no prompt, 1 file < 10MiB, 1 file > 10MiB
105 fossil clean --no-prompt
106 test clean-10 {[normalize_result] eq \
107 {"fossil undo" is available to undo changes to the working checkout.}}
108
109 ####################################
110
111 fossil undo -expectError
112 test clean-23 {[normalize_result] eq {nothing to undo}}
113
114 ###############################################################################
115
116 # clean w/undo disabled, force, 1 file < 10MiB, 1 file > 10MiB
117 fossil clean --disable-undo --force
118 test clean-24 {[normalize_result] eq {}}
119
120 ###############################################################################
121
122 fossil extra
123 test clean-25 {[normalize_result] eq {}}
124
125 ######################################
126 test clean-26 {[normalize_result] eq {nothing to undo}}
127
128 ###############################################################################
129
130 write_file f5 "f5 line"
131 fossil extra
132 test clean-27 {[normalize_result] eq {f5}}
133
134 ###############################################################################
135
136 # clean w/undo disabled, should prompt, 1 file < 10MiB
137 fossil_maybe_answer Y clean --disable-undo
138 test clean-28 {[normalize_result] eq \
139 {WARNING: Deletion of this file will not be undoable via the 'undo'
140 command because undo is disabled for this operation.
141
142 Remove unmanaged file "f5" (a=all/y/N)?}}
143
144 ###############################################################################
145
146 fossil extra
147 test clean-29 {[normalize_result] eq {}}
148
149 ###############################################################################
150
151 fossil undo
152 test clean-30 {[normalize_result] eq {nothing to undo}}
153
154 ###############################################################################
155
156 fossil extra
157 test clean-31 {[normalize_result] eq {}}
+26 -2
--- test/tester.tcl
+++ test/tester.tcl
@@ -87,22 +87,46 @@
8787
puts $out $msg
8888
close $out
8989
}
9090
}
9191
92
-# Run the fossil program
92
+# Run the Fossil program with the specified arguments.
93
+#
94
+# Consults the VERBOSE global variable to determine if
95
+# diagnostics should be emitted when no error is seen.
96
+# Sets the CODE and RESULT global variables for use in
97
+# test expressions.
9398
#
9499
proc fossil {args} {
100
+ return [uplevel 1 fossil_maybe_answer [list ""] $args]
101
+}
102
+
103
+# Run the Fossil program with the specified arguments
104
+# and possibly answer the first prompt, if any.
105
+#
106
+# Consults the VERBOSE global variable to determine if
107
+# diagnostics should be emitted when no error is seen.
108
+# Sets the CODE and RESULT global variables for use in
109
+# test expressions.
110
+#
111
+proc fossil_maybe_answer {answer args} {
95112
global fossilexe
96113
set cmd $fossilexe
97114
foreach a $args {
98115
lappend cmd $a
99116
}
100117
protOut $cmd
101118
102119
flush stdout
103
- set rc [catch {eval exec $cmd} result]
120
+ if {[string length $answer] > 0} {
121
+ set prompt_file [file join $::tempPath fossil_prompt_answer]
122
+ write_file $prompt_file $answer\n
123
+ set rc [catch {eval exec $cmd <$prompt_file} result]
124
+ file delete $prompt_file
125
+ } else {
126
+ set rc [catch {eval exec $cmd} result]
127
+ }
104128
global RESULT CODE
105129
set CODE $rc
106130
if {$rc} {
107131
protOut "ERROR: $result"
108132
} elseif {$::VERBOSE} {
109133
--- test/tester.tcl
+++ test/tester.tcl
@@ -87,22 +87,46 @@
87 puts $out $msg
88 close $out
89 }
90 }
91
92 # Run the fossil program
 
 
 
 
 
93 #
94 proc fossil {args} {
 
 
 
 
 
 
 
 
 
 
 
 
95 global fossilexe
96 set cmd $fossilexe
97 foreach a $args {
98 lappend cmd $a
99 }
100 protOut $cmd
101
102 flush stdout
103 set rc [catch {eval exec $cmd} result]
 
 
 
 
 
 
 
104 global RESULT CODE
105 set CODE $rc
106 if {$rc} {
107 protOut "ERROR: $result"
108 } elseif {$::VERBOSE} {
109
--- test/tester.tcl
+++ test/tester.tcl
@@ -87,22 +87,46 @@
87 puts $out $msg
88 close $out
89 }
90 }
91
92 # Run the Fossil program with the specified arguments.
93 #
94 # Consults the VERBOSE global variable to determine if
95 # diagnostics should be emitted when no error is seen.
96 # Sets the CODE and RESULT global variables for use in
97 # test expressions.
98 #
99 proc fossil {args} {
100 return [uplevel 1 fossil_maybe_answer [list ""] $args]
101 }
102
103 # Run the Fossil program with the specified arguments
104 # and possibly answer the first prompt, if any.
105 #
106 # Consults the VERBOSE global variable to determine if
107 # diagnostics should be emitted when no error is seen.
108 # Sets the CODE and RESULT global variables for use in
109 # test expressions.
110 #
111 proc fossil_maybe_answer {answer args} {
112 global fossilexe
113 set cmd $fossilexe
114 foreach a $args {
115 lappend cmd $a
116 }
117 protOut $cmd
118
119 flush stdout
120 if {[string length $answer] > 0} {
121 set prompt_file [file join $::tempPath fossil_prompt_answer]
122 write_file $prompt_file $answer\n
123 set rc [catch {eval exec $cmd <$prompt_file} result]
124 file delete $prompt_file
125 } else {
126 set rc [catch {eval exec $cmd} result]
127 }
128 global RESULT CODE
129 set CODE $rc
130 if {$rc} {
131 protOut "ERROR: $result"
132 } elseif {$::VERBOSE} {
133

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button