Fossil SCM
Updates to the "fossil clean" command: Added the -i/--prompt option. Always report if unable to delete a file. Fixed memory leaks and over-length source code lines.
Commit
c985d905c67d993157cc35563d8fa0b858ed910f
Parent
653b6b92404c53f…
1 file changed
+35
-12
+35
-12
| --- src/checkin.c | ||
| +++ src/checkin.c | ||
| @@ -2,11 +2,11 @@ | ||
| 2 | 2 | ** Copyright (c) 2007 D. Richard Hipp |
| 3 | 3 | ** |
| 4 | 4 | ** This program is free software; you can redistribute it and/or |
| 5 | 5 | ** modify it under the terms of the Simplified BSD License (also |
| 6 | 6 | ** known as the "2-Clause License" or "FreeBSD License".) |
| 7 | - | |
| 7 | +** | |
| 8 | 8 | ** This program is distributed in the hope that it will be useful, |
| 9 | 9 | ** but without any warranty; without even the implied warranty of |
| 10 | 10 | ** merchantability or fitness for a particular purpose. |
| 11 | 11 | ** |
| 12 | 12 | ** Author contact information: |
| @@ -62,11 +62,12 @@ | ||
| 62 | 62 | zName, filename_collation() |
| 63 | 63 | ); |
| 64 | 64 | } |
| 65 | 65 | |
| 66 | 66 | db_prepare(&q, |
| 67 | - "SELECT pathname, deleted, chnged, rid, coalesce(origname!=pathname,0), islink" | |
| 67 | + "SELECT pathname, deleted, chnged," | |
| 68 | + " rid, coalesce(origname!=pathname,0), islink" | |
| 68 | 69 | " FROM vfile " |
| 69 | 70 | " WHERE is_selected(id) %s" |
| 70 | 71 | " AND (chnged OR deleted OR rid=0 OR pathname!=origname)" |
| 71 | 72 | " ORDER BY 1 /*scan*/", |
| 72 | 73 | blob_sql_text(&where) |
| @@ -435,11 +436,12 @@ | ||
| 435 | 436 | " ORDER BY %s", |
| 436 | 437 | vid, timeline_utc(), blob_sql_text(&where), zOrderBy /*safe-for-%s*/ |
| 437 | 438 | ); |
| 438 | 439 | }else{ |
| 439 | 440 | db_prepare(&q, |
| 440 | - "SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0), islink" | |
| 441 | + "SELECT pathname, deleted, rid, chnged," | |
| 442 | + " coalesce(origname!=pathname,0), islink" | |
| 441 | 443 | " FROM vfile %s" |
| 442 | 444 | " ORDER BY %s", blob_sql_text(&where), zOrderBy /*safe-for-%s*/ |
| 443 | 445 | ); |
| 444 | 446 | } |
| 445 | 447 | blob_reset(&where); |
| @@ -672,10 +674,11 @@ | ||
| 672 | 674 | ** argument. Matching files, if any, are removed |
| 673 | 675 | ** prior to checking for any empty directories; |
| 674 | 676 | ** therefore, directories that contain only files |
| 675 | 677 | ** that were removed will be removed as well. |
| 676 | 678 | ** -f|--force Remove files without prompting. |
| 679 | +** -i|--prompt Prompt before removing each file. | |
| 677 | 680 | ** -x|--verily WARNING: Removes everything that is not a managed |
| 678 | 681 | ** file or the repository itself. This option |
| 679 | 682 | ** implies the --force, --emptydirs, --dotfiles, and |
| 680 | 683 | ** --disable-undo options. Furthermore, it completely |
| 681 | 684 | ** disregards the keep-glob and ignore-glob settings. |
| @@ -700,10 +703,11 @@ | ||
| 700 | 703 | */ |
| 701 | 704 | void clean_cmd(void){ |
| 702 | 705 | int allFileFlag, allDirFlag, dryRunFlag, verboseFlag; |
| 703 | 706 | int emptyDirsFlag, dirsOnlyFlag; |
| 704 | 707 | int disableUndo, noPrompt; |
| 708 | + int alwaysPrompt = 0; | |
| 705 | 709 | unsigned scanFlags = 0; |
| 706 | 710 | int verilyFlag = 0; |
| 707 | 711 | const char *zIgnoreFlag, *zKeepFlag, *zCleanFlag; |
| 708 | 712 | Glob *pIgnore, *pKeep, *pClean; |
| 709 | 713 | int nRoot; |
| @@ -720,10 +724,11 @@ | ||
| 720 | 724 | if( !dryRunFlag ){ |
| 721 | 725 | dryRunFlag = find_option("whatif",0,0)!=0; |
| 722 | 726 | } |
| 723 | 727 | disableUndo = find_option("disable-undo",0,0)!=0; |
| 724 | 728 | noPrompt = find_option("no-prompt",0,0)!=0; |
| 729 | + alwaysPrompt = find_option("prompt","i",0)!=0; | |
| 725 | 730 | allFileFlag = allDirFlag = find_option("force","f",0)!=0; |
| 726 | 731 | dirsOnlyFlag = find_option("dirsonly",0,0)!=0; |
| 727 | 732 | emptyDirsFlag = find_option("emptydirs","d",0)!=0 || dirsOnlyFlag; |
| 728 | 733 | if( find_option("dotfiles",0,0)!=0 ) scanFlags |= SCAN_ALL; |
| 729 | 734 | if( find_option("temp",0,0)!=0 ) scanFlags |= SCAN_TEMP; |
| @@ -779,26 +784,43 @@ | ||
| 779 | 784 | " or \"keep-glob\")\n", zName+nRoot); |
| 780 | 785 | } |
| 781 | 786 | continue; |
| 782 | 787 | } |
| 783 | 788 | if( !dryRunFlag && !glob_match(pClean, zName+nRoot) ){ |
| 789 | + char *zPrompt = 0; | |
| 790 | + char cReply; | |
| 791 | + Blob ans = empty_blob; | |
| 784 | 792 | int undoRc = UNDO_NONE; |
| 785 | - if( !disableUndo ){ | |
| 793 | + if( alwaysPrompt ){ | |
| 794 | + zPrompt = mprintf("Remove unmanaged file \"%s\" (a=all/y/N)? ", | |
| 795 | + zName+nRoot); | |
| 796 | + prompt_user(zPrompt, &ans); | |
| 797 | + fossil_free(zPrompt); | |
| 798 | + cReply = fossil_toupper(blob_str(&ans)[0]); | |
| 799 | + blob_reset(&ans); | |
| 800 | + if( cReply=='N' ) continue; | |
| 801 | + if( cReply=='A' ){ | |
| 802 | + allFileFlag = 1; | |
| 803 | + alwaysPrompt = 0; | |
| 804 | + }else{ | |
| 805 | + undoRc = UNDO_SAVED_OK; | |
| 806 | + } | |
| 807 | + }else if( !disableUndo ){ | |
| 786 | 808 | undoRc = undo_maybe_save(zName+nRoot, UNDO_SIZE_LIMIT); |
| 787 | 809 | } |
| 788 | 810 | if( undoRc!=UNDO_SAVED_OK ){ |
| 789 | - char cReply; | |
| 790 | 811 | if( allFileFlag ){ |
| 791 | 812 | cReply = 'Y'; |
| 792 | 813 | }else if( !noPrompt ){ |
| 793 | 814 | Blob ans; |
| 794 | - char *prompt = mprintf("\nWARNING: Deletion of this file will " | |
| 795 | - "not be undoable via the 'undo'\n" | |
| 796 | - " command because %s.\n\n" | |
| 797 | - "Remove unmanaged file \"%s\" (a=all/y/N)? ", | |
| 798 | - undo_save_message(undoRc), zName+nRoot); | |
| 799 | - prompt_user(prompt, &ans); | |
| 815 | + zPrompt = mprintf("\nWARNING: Deletion of this file will " | |
| 816 | + "not be undoable via the 'undo'\n" | |
| 817 | + " command because %s.\n\n" | |
| 818 | + "Remove unmanaged file \"%s\" (a=all/y/N)? ", | |
| 819 | + undo_save_message(undoRc), zName+nRoot); | |
| 820 | + prompt_user(zPrompt, &ans); | |
| 821 | + fossil_free(zPrompt); | |
| 800 | 822 | cReply = blob_str(&ans)[0]; |
| 801 | 823 | blob_reset(&ans); |
| 802 | 824 | }else{ |
| 803 | 825 | cReply = 'N'; |
| 804 | 826 | } |
| @@ -811,11 +833,11 @@ | ||
| 811 | 833 | } |
| 812 | 834 | if( dryRunFlag || file_delete(zName)==0 ){ |
| 813 | 835 | if( verboseFlag || dryRunFlag ){ |
| 814 | 836 | fossil_print("Removed unmanaged file: %s\n", zName+nRoot); |
| 815 | 837 | } |
| 816 | - }else if( verboseFlag ){ | |
| 838 | + }else{ | |
| 817 | 839 | fossil_print("Could not remove file: %s\n", zName+nRoot); |
| 818 | 840 | } |
| 819 | 841 | } |
| 820 | 842 | db_finalize(&q); |
| 821 | 843 | if( !dryRunFlag && !disableUndo ) undo_finish(); |
| @@ -849,10 +871,11 @@ | ||
| 849 | 871 | Blob ans; |
| 850 | 872 | char *prompt = mprintf("Remove empty directory \"%s\" (a=all/y/N)? ", |
| 851 | 873 | zName+nRoot); |
| 852 | 874 | prompt_user(prompt, &ans); |
| 853 | 875 | cReply = blob_str(&ans)[0]; |
| 876 | + fossil_free(prompt); | |
| 854 | 877 | blob_reset(&ans); |
| 855 | 878 | }else{ |
| 856 | 879 | cReply = 'N'; |
| 857 | 880 | } |
| 858 | 881 | if( cReply=='a' || cReply=='A' ){ |
| 859 | 882 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -2,11 +2,11 @@ | |
| 2 | ** Copyright (c) 2007 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: |
| @@ -62,11 +62,12 @@ | |
| 62 | zName, filename_collation() |
| 63 | ); |
| 64 | } |
| 65 | |
| 66 | db_prepare(&q, |
| 67 | "SELECT pathname, deleted, chnged, rid, coalesce(origname!=pathname,0), islink" |
| 68 | " FROM vfile " |
| 69 | " WHERE is_selected(id) %s" |
| 70 | " AND (chnged OR deleted OR rid=0 OR pathname!=origname)" |
| 71 | " ORDER BY 1 /*scan*/", |
| 72 | blob_sql_text(&where) |
| @@ -435,11 +436,12 @@ | |
| 435 | " ORDER BY %s", |
| 436 | vid, timeline_utc(), blob_sql_text(&where), zOrderBy /*safe-for-%s*/ |
| 437 | ); |
| 438 | }else{ |
| 439 | db_prepare(&q, |
| 440 | "SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0), islink" |
| 441 | " FROM vfile %s" |
| 442 | " ORDER BY %s", blob_sql_text(&where), zOrderBy /*safe-for-%s*/ |
| 443 | ); |
| 444 | } |
| 445 | blob_reset(&where); |
| @@ -672,10 +674,11 @@ | |
| 672 | ** argument. Matching files, if any, are removed |
| 673 | ** prior to checking for any empty directories; |
| 674 | ** therefore, directories that contain only files |
| 675 | ** that were removed will be removed as well. |
| 676 | ** -f|--force Remove files without prompting. |
| 677 | ** -x|--verily WARNING: Removes everything that is not a managed |
| 678 | ** file or the repository itself. This option |
| 679 | ** implies the --force, --emptydirs, --dotfiles, and |
| 680 | ** --disable-undo options. Furthermore, it completely |
| 681 | ** disregards the keep-glob and ignore-glob settings. |
| @@ -700,10 +703,11 @@ | |
| 700 | */ |
| 701 | void clean_cmd(void){ |
| 702 | int allFileFlag, allDirFlag, dryRunFlag, verboseFlag; |
| 703 | int emptyDirsFlag, dirsOnlyFlag; |
| 704 | int disableUndo, noPrompt; |
| 705 | unsigned scanFlags = 0; |
| 706 | int verilyFlag = 0; |
| 707 | const char *zIgnoreFlag, *zKeepFlag, *zCleanFlag; |
| 708 | Glob *pIgnore, *pKeep, *pClean; |
| 709 | int nRoot; |
| @@ -720,10 +724,11 @@ | |
| 720 | if( !dryRunFlag ){ |
| 721 | dryRunFlag = find_option("whatif",0,0)!=0; |
| 722 | } |
| 723 | disableUndo = find_option("disable-undo",0,0)!=0; |
| 724 | noPrompt = find_option("no-prompt",0,0)!=0; |
| 725 | allFileFlag = allDirFlag = find_option("force","f",0)!=0; |
| 726 | dirsOnlyFlag = find_option("dirsonly",0,0)!=0; |
| 727 | emptyDirsFlag = find_option("emptydirs","d",0)!=0 || dirsOnlyFlag; |
| 728 | if( find_option("dotfiles",0,0)!=0 ) scanFlags |= SCAN_ALL; |
| 729 | if( find_option("temp",0,0)!=0 ) scanFlags |= SCAN_TEMP; |
| @@ -779,26 +784,43 @@ | |
| 779 | " or \"keep-glob\")\n", zName+nRoot); |
| 780 | } |
| 781 | continue; |
| 782 | } |
| 783 | if( !dryRunFlag && !glob_match(pClean, zName+nRoot) ){ |
| 784 | int undoRc = UNDO_NONE; |
| 785 | if( !disableUndo ){ |
| 786 | undoRc = undo_maybe_save(zName+nRoot, UNDO_SIZE_LIMIT); |
| 787 | } |
| 788 | if( undoRc!=UNDO_SAVED_OK ){ |
| 789 | char cReply; |
| 790 | if( allFileFlag ){ |
| 791 | cReply = 'Y'; |
| 792 | }else if( !noPrompt ){ |
| 793 | Blob ans; |
| 794 | char *prompt = mprintf("\nWARNING: Deletion of this file will " |
| 795 | "not be undoable via the 'undo'\n" |
| 796 | " command because %s.\n\n" |
| 797 | "Remove unmanaged file \"%s\" (a=all/y/N)? ", |
| 798 | undo_save_message(undoRc), zName+nRoot); |
| 799 | prompt_user(prompt, &ans); |
| 800 | cReply = blob_str(&ans)[0]; |
| 801 | blob_reset(&ans); |
| 802 | }else{ |
| 803 | cReply = 'N'; |
| 804 | } |
| @@ -811,11 +833,11 @@ | |
| 811 | } |
| 812 | if( dryRunFlag || file_delete(zName)==0 ){ |
| 813 | if( verboseFlag || dryRunFlag ){ |
| 814 | fossil_print("Removed unmanaged file: %s\n", zName+nRoot); |
| 815 | } |
| 816 | }else if( verboseFlag ){ |
| 817 | fossil_print("Could not remove file: %s\n", zName+nRoot); |
| 818 | } |
| 819 | } |
| 820 | db_finalize(&q); |
| 821 | if( !dryRunFlag && !disableUndo ) undo_finish(); |
| @@ -849,10 +871,11 @@ | |
| 849 | Blob ans; |
| 850 | char *prompt = mprintf("Remove empty directory \"%s\" (a=all/y/N)? ", |
| 851 | zName+nRoot); |
| 852 | prompt_user(prompt, &ans); |
| 853 | cReply = blob_str(&ans)[0]; |
| 854 | blob_reset(&ans); |
| 855 | }else{ |
| 856 | cReply = 'N'; |
| 857 | } |
| 858 | if( cReply=='a' || cReply=='A' ){ |
| 859 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -2,11 +2,11 @@ | |
| 2 | ** Copyright (c) 2007 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: |
| @@ -62,11 +62,12 @@ | |
| 62 | zName, filename_collation() |
| 63 | ); |
| 64 | } |
| 65 | |
| 66 | db_prepare(&q, |
| 67 | "SELECT pathname, deleted, chnged," |
| 68 | " rid, coalesce(origname!=pathname,0), islink" |
| 69 | " FROM vfile " |
| 70 | " WHERE is_selected(id) %s" |
| 71 | " AND (chnged OR deleted OR rid=0 OR pathname!=origname)" |
| 72 | " ORDER BY 1 /*scan*/", |
| 73 | blob_sql_text(&where) |
| @@ -435,11 +436,12 @@ | |
| 436 | " ORDER BY %s", |
| 437 | vid, timeline_utc(), blob_sql_text(&where), zOrderBy /*safe-for-%s*/ |
| 438 | ); |
| 439 | }else{ |
| 440 | db_prepare(&q, |
| 441 | "SELECT pathname, deleted, rid, chnged," |
| 442 | " coalesce(origname!=pathname,0), islink" |
| 443 | " FROM vfile %s" |
| 444 | " ORDER BY %s", blob_sql_text(&where), zOrderBy /*safe-for-%s*/ |
| 445 | ); |
| 446 | } |
| 447 | blob_reset(&where); |
| @@ -672,10 +674,11 @@ | |
| 674 | ** argument. Matching files, if any, are removed |
| 675 | ** prior to checking for any empty directories; |
| 676 | ** therefore, directories that contain only files |
| 677 | ** that were removed will be removed as well. |
| 678 | ** -f|--force Remove files without prompting. |
| 679 | ** -i|--prompt Prompt before removing each file. |
| 680 | ** -x|--verily WARNING: Removes everything that is not a managed |
| 681 | ** file or the repository itself. This option |
| 682 | ** implies the --force, --emptydirs, --dotfiles, and |
| 683 | ** --disable-undo options. Furthermore, it completely |
| 684 | ** disregards the keep-glob and ignore-glob settings. |
| @@ -700,10 +703,11 @@ | |
| 703 | */ |
| 704 | void clean_cmd(void){ |
| 705 | int allFileFlag, allDirFlag, dryRunFlag, verboseFlag; |
| 706 | int emptyDirsFlag, dirsOnlyFlag; |
| 707 | int disableUndo, noPrompt; |
| 708 | int alwaysPrompt = 0; |
| 709 | unsigned scanFlags = 0; |
| 710 | int verilyFlag = 0; |
| 711 | const char *zIgnoreFlag, *zKeepFlag, *zCleanFlag; |
| 712 | Glob *pIgnore, *pKeep, *pClean; |
| 713 | int nRoot; |
| @@ -720,10 +724,11 @@ | |
| 724 | if( !dryRunFlag ){ |
| 725 | dryRunFlag = find_option("whatif",0,0)!=0; |
| 726 | } |
| 727 | disableUndo = find_option("disable-undo",0,0)!=0; |
| 728 | noPrompt = find_option("no-prompt",0,0)!=0; |
| 729 | alwaysPrompt = find_option("prompt","i",0)!=0; |
| 730 | allFileFlag = allDirFlag = find_option("force","f",0)!=0; |
| 731 | dirsOnlyFlag = find_option("dirsonly",0,0)!=0; |
| 732 | emptyDirsFlag = find_option("emptydirs","d",0)!=0 || dirsOnlyFlag; |
| 733 | if( find_option("dotfiles",0,0)!=0 ) scanFlags |= SCAN_ALL; |
| 734 | if( find_option("temp",0,0)!=0 ) scanFlags |= SCAN_TEMP; |
| @@ -779,26 +784,43 @@ | |
| 784 | " or \"keep-glob\")\n", zName+nRoot); |
| 785 | } |
| 786 | continue; |
| 787 | } |
| 788 | if( !dryRunFlag && !glob_match(pClean, zName+nRoot) ){ |
| 789 | char *zPrompt = 0; |
| 790 | char cReply; |
| 791 | Blob ans = empty_blob; |
| 792 | int undoRc = UNDO_NONE; |
| 793 | if( alwaysPrompt ){ |
| 794 | zPrompt = mprintf("Remove unmanaged file \"%s\" (a=all/y/N)? ", |
| 795 | zName+nRoot); |
| 796 | prompt_user(zPrompt, &ans); |
| 797 | fossil_free(zPrompt); |
| 798 | cReply = fossil_toupper(blob_str(&ans)[0]); |
| 799 | blob_reset(&ans); |
| 800 | if( cReply=='N' ) continue; |
| 801 | if( cReply=='A' ){ |
| 802 | allFileFlag = 1; |
| 803 | alwaysPrompt = 0; |
| 804 | }else{ |
| 805 | undoRc = UNDO_SAVED_OK; |
| 806 | } |
| 807 | }else if( !disableUndo ){ |
| 808 | undoRc = undo_maybe_save(zName+nRoot, UNDO_SIZE_LIMIT); |
| 809 | } |
| 810 | if( undoRc!=UNDO_SAVED_OK ){ |
| 811 | if( allFileFlag ){ |
| 812 | cReply = 'Y'; |
| 813 | }else if( !noPrompt ){ |
| 814 | Blob ans; |
| 815 | zPrompt = mprintf("\nWARNING: Deletion of this file will " |
| 816 | "not be undoable via the 'undo'\n" |
| 817 | " command because %s.\n\n" |
| 818 | "Remove unmanaged file \"%s\" (a=all/y/N)? ", |
| 819 | undo_save_message(undoRc), zName+nRoot); |
| 820 | prompt_user(zPrompt, &ans); |
| 821 | fossil_free(zPrompt); |
| 822 | cReply = blob_str(&ans)[0]; |
| 823 | blob_reset(&ans); |
| 824 | }else{ |
| 825 | cReply = 'N'; |
| 826 | } |
| @@ -811,11 +833,11 @@ | |
| 833 | } |
| 834 | if( dryRunFlag || file_delete(zName)==0 ){ |
| 835 | if( verboseFlag || dryRunFlag ){ |
| 836 | fossil_print("Removed unmanaged file: %s\n", zName+nRoot); |
| 837 | } |
| 838 | }else{ |
| 839 | fossil_print("Could not remove file: %s\n", zName+nRoot); |
| 840 | } |
| 841 | } |
| 842 | db_finalize(&q); |
| 843 | if( !dryRunFlag && !disableUndo ) undo_finish(); |
| @@ -849,10 +871,11 @@ | |
| 871 | Blob ans; |
| 872 | char *prompt = mprintf("Remove empty directory \"%s\" (a=all/y/N)? ", |
| 873 | zName+nRoot); |
| 874 | prompt_user(prompt, &ans); |
| 875 | cReply = blob_str(&ans)[0]; |
| 876 | fossil_free(prompt); |
| 877 | blob_reset(&ans); |
| 878 | }else{ |
| 879 | cReply = 'N'; |
| 880 | } |
| 881 | if( cReply=='a' || cReply=='A' ){ |
| 882 |