Fossil SCM

Add the --dirsonly and --allckouts options to the 'clean' command.

mistachkin 2013-09-30 12:16 UTC cleanEmptyDirs
Commit 51403ee52e05833df6b26892b840f35f402ece86
2 files changed +56 -42 +2 -1
+56 -42
--- src/checkin.c
+++ src/checkin.c
@@ -507,11 +507,19 @@
507507
** Files and subdirectories whose names begin with "." are
508508
** normally kept. They are handled if the "--dotfiles" option
509509
** is used.
510510
**
511511
** Options:
512
+** --allckouts Check for empty directories within any checkouts
513
+** that may be nested within the current one. This
514
+** option should be used with great care because the
515
+** empty-dirs setting (and other applicable settings)
516
+** belonging to the other repositories, if any, will
517
+** not be checked.
512518
** --case-sensitive <BOOL> override case-sensitive setting
519
+** --dirsonly Only remove empty directories. No files will
520
+** be removed.
513521
** --dotfiles Include files beginning with a dot (".").
514522
** --emptydirs Remove any empty directories that are not
515523
** explicitly exempted via the empty-dirs setting
516524
** or another applicable setting or command line
517525
** argument. Matching files, if any, are removed
@@ -530,26 +538,27 @@
530538
** -v|--verbose Show all files as they are removed.
531539
**
532540
** See also: addremove, extra, status
533541
*/
534542
void clean_cmd(void){
535
- int allFileFlag, allDirFlag, dryRunFlag, emptyDirsFlag, verboseFlag;
543
+ int allFileFlag, allDirFlag, dryRunFlag, verboseFlag;
544
+ int emptyDirsFlag, dirsOnlyFlag;
536545
unsigned scanFlags = 0;
537546
const char *zIgnoreFlag, *zKeepFlag, *zCleanFlag;
538
- Blob repo;
539
- Stmt q;
540547
Glob *pIgnore, *pKeep, *pClean;
541548
int nRoot;
542549
543550
dryRunFlag = find_option("dry-run","n",0)!=0;
544551
if( !dryRunFlag ){
545552
dryRunFlag = find_option("test",0,0)!=0; /* deprecated */
546553
}
547554
allFileFlag = allDirFlag = find_option("force","f",0)!=0;
548555
emptyDirsFlag = find_option("emptydirs","d",0)!=0;
556
+ dirsOnlyFlag = find_option("dirsonly",0,0)!=0;
549557
if( find_option("dotfiles",0,0)!=0 ) scanFlags |= SCAN_ALL;
550558
if( find_option("temp",0,0)!=0 ) scanFlags |= SCAN_TEMP;
559
+ if( find_option("allckouts",0,0)!=0 ) scanFlags |= SCAN_NESTED;
551560
zIgnoreFlag = find_option("ignore",0,1);
552561
verboseFlag = find_option("verbose","v",0)!=0;
553562
zKeepFlag = find_option("keep",0,1);
554563
zCleanFlag = find_option("clean",0,1);
555564
capture_case_sensitive_option();
@@ -565,56 +574,61 @@
565574
}
566575
verify_all_options();
567576
pIgnore = glob_create(zIgnoreFlag);
568577
pKeep = glob_create(zKeepFlag);
569578
pClean = glob_create(zCleanFlag);
570
- locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore, pKeep);
571
- db_prepare(&q,
572
- "SELECT %Q || x FROM sfile"
573
- " WHERE x NOT IN (%s)"
574
- " ORDER BY 1",
575
- g.zLocalRoot, fossil_all_reserved_names(0)
576
- );
577
- if( file_tree_name(g.zRepositoryName, &repo, 0) ){
578
- db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo);
579
- }
580
- db_multi_exec("DELETE FROM sfile WHERE x IN (SELECT pathname FROM vfile)");
581
- nRoot = (int)strlen(g.zLocalRoot);
582
- while( db_step(&q)==SQLITE_ROW ){
583
- const char *zName = db_column_text(&q, 0);
584
- if( !allFileFlag && !dryRunFlag && !glob_match(pClean, zName+nRoot) ){
585
- Blob ans;
586
- char cReply;
587
- char *prompt = mprintf("Remove unmanaged file \"%s\" (a=all/y/N)? ",
588
- zName+nRoot);
589
- blob_zero(&ans);
590
- prompt_user(prompt, &ans);
591
- cReply = blob_str(&ans)[0];
592
- if( cReply=='a' || cReply=='A' ){
593
- allFileFlag = 1;
594
- }else if( cReply!='y' && cReply!='Y' ){
595
- blob_reset(&ans);
596
- continue;
597
- }
598
- blob_reset(&ans);
599
- }
600
- if ( dryRunFlag || file_delete(zName)==0 ){
601
- if( verboseFlag || dryRunFlag ){
602
- fossil_print("Removed unmanaged file: %s\n", zName+nRoot);
603
- }
604
- }else if( verboseFlag ){
605
- fossil_print("Could not remove file: %s\n", zName+nRoot);
606
- }
579
+ nRoot = (int)strlen(g.zLocalRoot);
580
+ if( !dirsOnlyFlag ){
581
+ Stmt q;
582
+ Blob repo;
583
+ locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore, pKeep);
584
+ db_prepare(&q,
585
+ "SELECT %Q || x FROM sfile"
586
+ " WHERE x NOT IN (%s)"
587
+ " ORDER BY 1",
588
+ g.zLocalRoot, fossil_all_reserved_names(0)
589
+ );
590
+ if( file_tree_name(g.zRepositoryName, &repo, 0) ){
591
+ db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo);
592
+ }
593
+ db_multi_exec("DELETE FROM sfile WHERE x IN (SELECT pathname FROM vfile)");
594
+ while( db_step(&q)==SQLITE_ROW ){
595
+ const char *zName = db_column_text(&q, 0);
596
+ if( !allFileFlag && !dryRunFlag && !glob_match(pClean, zName+nRoot) ){
597
+ Blob ans;
598
+ char cReply;
599
+ char *prompt = mprintf("Remove unmanaged file \"%s\" (a=all/y/N)? ",
600
+ zName+nRoot);
601
+ blob_zero(&ans);
602
+ prompt_user(prompt, &ans);
603
+ cReply = blob_str(&ans)[0];
604
+ if( cReply=='a' || cReply=='A' ){
605
+ allFileFlag = 1;
606
+ }else if( cReply!='y' && cReply!='Y' ){
607
+ blob_reset(&ans);
608
+ continue;
609
+ }
610
+ blob_reset(&ans);
611
+ }
612
+ if ( dryRunFlag || file_delete(zName)==0 ){
613
+ if( verboseFlag || dryRunFlag ){
614
+ fossil_print("Removed unmanaged file: %s\n", zName+nRoot);
615
+ }
616
+ }else if( verboseFlag ){
617
+ fossil_print("Could not remove file: %s\n", zName+nRoot);
618
+ }
619
+ }
620
+ db_finalize(&q);
607621
}
608622
if( emptyDirsFlag ){
609623
Glob *pEmptyDirs = glob_create(db_get("empty-dirs", 0));
624
+ Stmt q;
610625
Blob root;
611626
blob_init(&root, g.zLocalRoot, nRoot - 1);
612627
vfile_dir_scan(&root, blob_size(&root), scanFlags, pIgnore, pKeep,
613628
pEmptyDirs);
614629
blob_reset(&root);
615
- db_finalize(&q);
616630
db_prepare(&q,
617631
"SELECT %Q || x FROM dscan_temp"
618632
" WHERE x NOT IN (%s) AND y = 0"
619633
" ORDER BY 1 DESC",
620634
g.zLocalRoot, fossil_all_reserved_names(0)
@@ -643,16 +657,16 @@
643657
}
644658
}else if( verboseFlag ){
645659
fossil_print("Could not remove directory: %s\n", zName+nRoot);
646660
}
647661
}
662
+ db_finalize(&q);
648663
glob_free(pEmptyDirs);
649664
}
650665
glob_free(pClean);
651666
glob_free(pKeep);
652667
glob_free(pIgnore);
653
- db_finalize(&q);
654668
}
655669
656670
/*
657671
** Prompt the user for a check-in or stash comment (given in pPrompt),
658672
** gather the response, then return the response in pComment.
659673
--- src/checkin.c
+++ src/checkin.c
@@ -507,11 +507,19 @@
507 ** Files and subdirectories whose names begin with "." are
508 ** normally kept. They are handled if the "--dotfiles" option
509 ** is used.
510 **
511 ** Options:
 
 
 
 
 
 
512 ** --case-sensitive <BOOL> override case-sensitive setting
 
 
513 ** --dotfiles Include files beginning with a dot (".").
514 ** --emptydirs Remove any empty directories that are not
515 ** explicitly exempted via the empty-dirs setting
516 ** or another applicable setting or command line
517 ** argument. Matching files, if any, are removed
@@ -530,26 +538,27 @@
530 ** -v|--verbose Show all files as they are removed.
531 **
532 ** See also: addremove, extra, status
533 */
534 void clean_cmd(void){
535 int allFileFlag, allDirFlag, dryRunFlag, emptyDirsFlag, verboseFlag;
 
536 unsigned scanFlags = 0;
537 const char *zIgnoreFlag, *zKeepFlag, *zCleanFlag;
538 Blob repo;
539 Stmt q;
540 Glob *pIgnore, *pKeep, *pClean;
541 int nRoot;
542
543 dryRunFlag = find_option("dry-run","n",0)!=0;
544 if( !dryRunFlag ){
545 dryRunFlag = find_option("test",0,0)!=0; /* deprecated */
546 }
547 allFileFlag = allDirFlag = find_option("force","f",0)!=0;
548 emptyDirsFlag = find_option("emptydirs","d",0)!=0;
 
549 if( find_option("dotfiles",0,0)!=0 ) scanFlags |= SCAN_ALL;
550 if( find_option("temp",0,0)!=0 ) scanFlags |= SCAN_TEMP;
 
551 zIgnoreFlag = find_option("ignore",0,1);
552 verboseFlag = find_option("verbose","v",0)!=0;
553 zKeepFlag = find_option("keep",0,1);
554 zCleanFlag = find_option("clean",0,1);
555 capture_case_sensitive_option();
@@ -565,56 +574,61 @@
565 }
566 verify_all_options();
567 pIgnore = glob_create(zIgnoreFlag);
568 pKeep = glob_create(zKeepFlag);
569 pClean = glob_create(zCleanFlag);
570 locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore, pKeep);
571 db_prepare(&q,
572 "SELECT %Q || x FROM sfile"
573 " WHERE x NOT IN (%s)"
574 " ORDER BY 1",
575 g.zLocalRoot, fossil_all_reserved_names(0)
576 );
577 if( file_tree_name(g.zRepositoryName, &repo, 0) ){
578 db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo);
579 }
580 db_multi_exec("DELETE FROM sfile WHERE x IN (SELECT pathname FROM vfile)");
581 nRoot = (int)strlen(g.zLocalRoot);
582 while( db_step(&q)==SQLITE_ROW ){
583 const char *zName = db_column_text(&q, 0);
584 if( !allFileFlag && !dryRunFlag && !glob_match(pClean, zName+nRoot) ){
585 Blob ans;
586 char cReply;
587 char *prompt = mprintf("Remove unmanaged file \"%s\" (a=all/y/N)? ",
588 zName+nRoot);
589 blob_zero(&ans);
590 prompt_user(prompt, &ans);
591 cReply = blob_str(&ans)[0];
592 if( cReply=='a' || cReply=='A' ){
593 allFileFlag = 1;
594 }else if( cReply!='y' && cReply!='Y' ){
595 blob_reset(&ans);
596 continue;
597 }
598 blob_reset(&ans);
599 }
600 if ( dryRunFlag || file_delete(zName)==0 ){
601 if( verboseFlag || dryRunFlag ){
602 fossil_print("Removed unmanaged file: %s\n", zName+nRoot);
603 }
604 }else if( verboseFlag ){
605 fossil_print("Could not remove file: %s\n", zName+nRoot);
606 }
 
 
 
 
 
607 }
608 if( emptyDirsFlag ){
609 Glob *pEmptyDirs = glob_create(db_get("empty-dirs", 0));
 
610 Blob root;
611 blob_init(&root, g.zLocalRoot, nRoot - 1);
612 vfile_dir_scan(&root, blob_size(&root), scanFlags, pIgnore, pKeep,
613 pEmptyDirs);
614 blob_reset(&root);
615 db_finalize(&q);
616 db_prepare(&q,
617 "SELECT %Q || x FROM dscan_temp"
618 " WHERE x NOT IN (%s) AND y = 0"
619 " ORDER BY 1 DESC",
620 g.zLocalRoot, fossil_all_reserved_names(0)
@@ -643,16 +657,16 @@
643 }
644 }else if( verboseFlag ){
645 fossil_print("Could not remove directory: %s\n", zName+nRoot);
646 }
647 }
 
648 glob_free(pEmptyDirs);
649 }
650 glob_free(pClean);
651 glob_free(pKeep);
652 glob_free(pIgnore);
653 db_finalize(&q);
654 }
655
656 /*
657 ** Prompt the user for a check-in or stash comment (given in pPrompt),
658 ** gather the response, then return the response in pComment.
659
--- src/checkin.c
+++ src/checkin.c
@@ -507,11 +507,19 @@
507 ** Files and subdirectories whose names begin with "." are
508 ** normally kept. They are handled if the "--dotfiles" option
509 ** is used.
510 **
511 ** Options:
512 ** --allckouts Check for empty directories within any checkouts
513 ** that may be nested within the current one. This
514 ** option should be used with great care because the
515 ** empty-dirs setting (and other applicable settings)
516 ** belonging to the other repositories, if any, will
517 ** not be checked.
518 ** --case-sensitive <BOOL> override case-sensitive setting
519 ** --dirsonly Only remove empty directories. No files will
520 ** be removed.
521 ** --dotfiles Include files beginning with a dot (".").
522 ** --emptydirs Remove any empty directories that are not
523 ** explicitly exempted via the empty-dirs setting
524 ** or another applicable setting or command line
525 ** argument. Matching files, if any, are removed
@@ -530,26 +538,27 @@
538 ** -v|--verbose Show all files as they are removed.
539 **
540 ** See also: addremove, extra, status
541 */
542 void clean_cmd(void){
543 int allFileFlag, allDirFlag, dryRunFlag, verboseFlag;
544 int emptyDirsFlag, dirsOnlyFlag;
545 unsigned scanFlags = 0;
546 const char *zIgnoreFlag, *zKeepFlag, *zCleanFlag;
 
 
547 Glob *pIgnore, *pKeep, *pClean;
548 int nRoot;
549
550 dryRunFlag = find_option("dry-run","n",0)!=0;
551 if( !dryRunFlag ){
552 dryRunFlag = find_option("test",0,0)!=0; /* deprecated */
553 }
554 allFileFlag = allDirFlag = find_option("force","f",0)!=0;
555 emptyDirsFlag = find_option("emptydirs","d",0)!=0;
556 dirsOnlyFlag = find_option("dirsonly",0,0)!=0;
557 if( find_option("dotfiles",0,0)!=0 ) scanFlags |= SCAN_ALL;
558 if( find_option("temp",0,0)!=0 ) scanFlags |= SCAN_TEMP;
559 if( find_option("allckouts",0,0)!=0 ) scanFlags |= SCAN_NESTED;
560 zIgnoreFlag = find_option("ignore",0,1);
561 verboseFlag = find_option("verbose","v",0)!=0;
562 zKeepFlag = find_option("keep",0,1);
563 zCleanFlag = find_option("clean",0,1);
564 capture_case_sensitive_option();
@@ -565,56 +574,61 @@
574 }
575 verify_all_options();
576 pIgnore = glob_create(zIgnoreFlag);
577 pKeep = glob_create(zKeepFlag);
578 pClean = glob_create(zCleanFlag);
579 nRoot = (int)strlen(g.zLocalRoot);
580 if( !dirsOnlyFlag ){
581 Stmt q;
582 Blob repo;
583 locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore, pKeep);
584 db_prepare(&q,
585 "SELECT %Q || x FROM sfile"
586 " WHERE x NOT IN (%s)"
587 " ORDER BY 1",
588 g.zLocalRoot, fossil_all_reserved_names(0)
589 );
590 if( file_tree_name(g.zRepositoryName, &repo, 0) ){
591 db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo);
592 }
593 db_multi_exec("DELETE FROM sfile WHERE x IN (SELECT pathname FROM vfile)");
594 while( db_step(&q)==SQLITE_ROW ){
595 const char *zName = db_column_text(&q, 0);
596 if( !allFileFlag && !dryRunFlag && !glob_match(pClean, zName+nRoot) ){
597 Blob ans;
598 char cReply;
599 char *prompt = mprintf("Remove unmanaged file \"%s\" (a=all/y/N)? ",
600 zName+nRoot);
601 blob_zero(&ans);
602 prompt_user(prompt, &ans);
603 cReply = blob_str(&ans)[0];
604 if( cReply=='a' || cReply=='A' ){
605 allFileFlag = 1;
606 }else if( cReply!='y' && cReply!='Y' ){
607 blob_reset(&ans);
608 continue;
609 }
610 blob_reset(&ans);
611 }
612 if ( dryRunFlag || file_delete(zName)==0 ){
613 if( verboseFlag || dryRunFlag ){
614 fossil_print("Removed unmanaged file: %s\n", zName+nRoot);
615 }
616 }else if( verboseFlag ){
617 fossil_print("Could not remove file: %s\n", zName+nRoot);
618 }
619 }
620 db_finalize(&q);
621 }
622 if( emptyDirsFlag ){
623 Glob *pEmptyDirs = glob_create(db_get("empty-dirs", 0));
624 Stmt q;
625 Blob root;
626 blob_init(&root, g.zLocalRoot, nRoot - 1);
627 vfile_dir_scan(&root, blob_size(&root), scanFlags, pIgnore, pKeep,
628 pEmptyDirs);
629 blob_reset(&root);
 
630 db_prepare(&q,
631 "SELECT %Q || x FROM dscan_temp"
632 " WHERE x NOT IN (%s) AND y = 0"
633 " ORDER BY 1 DESC",
634 g.zLocalRoot, fossil_all_reserved_names(0)
@@ -643,16 +657,16 @@
657 }
658 }else if( verboseFlag ){
659 fossil_print("Could not remove directory: %s\n", zName+nRoot);
660 }
661 }
662 db_finalize(&q);
663 glob_free(pEmptyDirs);
664 }
665 glob_free(pClean);
666 glob_free(pKeep);
667 glob_free(pIgnore);
 
668 }
669
670 /*
671 ** Prompt the user for a check-in or stash comment (given in pPrompt),
672 ** gather the response, then return the response in pComment.
673
+2 -1
--- src/vfile.c
+++ src/vfile.c
@@ -418,10 +418,11 @@
418418
/*
419419
** Values for the scanFlags parameter to vfile_scan().
420420
*/
421421
#define SCAN_ALL 0x001 /* Includes files that begin with "." */
422422
#define SCAN_TEMP 0x002 /* Only Fossil-generated files like *-baseline */
423
+#define SCAN_NESTED 0x004 /* Scan for empty dirs in nested checkouts */
423424
#endif /* INTERFACE */
424425
425426
/*
426427
** Load into table SFILE the name of every ordinary file in
427428
** the directory pPath. Omit the first nPrefix characters of
@@ -593,11 +594,11 @@
593594
if( glob_match(pIgnore1, &zPath[nPrefix+1]) ||
594595
glob_match(pIgnore2, &zPath[nPrefix+1]) ||
595596
glob_match(pIgnore3, &zPath[nPrefix+1]) ){
596597
/* do nothing */
597598
}else if( file_wd_isdir(zPath)==1 ){
598
- if( !vfile_top_of_checkout(zPath) ){
599
+ if( (scanFlags & SCAN_NESTED) || !vfile_top_of_checkout(zPath) ){
599600
Blob dirPattern;
600601
int count = vfile_dir_scan(pPath, nPrefix, scanFlags, pIgnore1,
601602
pIgnore2, pIgnore3);
602603
blob_init(&dirPattern, &zPath[nPrefix+1], -1);
603604
blob_appendf(&dirPattern, "*");
604605
--- src/vfile.c
+++ src/vfile.c
@@ -418,10 +418,11 @@
418 /*
419 ** Values for the scanFlags parameter to vfile_scan().
420 */
421 #define SCAN_ALL 0x001 /* Includes files that begin with "." */
422 #define SCAN_TEMP 0x002 /* Only Fossil-generated files like *-baseline */
 
423 #endif /* INTERFACE */
424
425 /*
426 ** Load into table SFILE the name of every ordinary file in
427 ** the directory pPath. Omit the first nPrefix characters of
@@ -593,11 +594,11 @@
593 if( glob_match(pIgnore1, &zPath[nPrefix+1]) ||
594 glob_match(pIgnore2, &zPath[nPrefix+1]) ||
595 glob_match(pIgnore3, &zPath[nPrefix+1]) ){
596 /* do nothing */
597 }else if( file_wd_isdir(zPath)==1 ){
598 if( !vfile_top_of_checkout(zPath) ){
599 Blob dirPattern;
600 int count = vfile_dir_scan(pPath, nPrefix, scanFlags, pIgnore1,
601 pIgnore2, pIgnore3);
602 blob_init(&dirPattern, &zPath[nPrefix+1], -1);
603 blob_appendf(&dirPattern, "*");
604
--- src/vfile.c
+++ src/vfile.c
@@ -418,10 +418,11 @@
418 /*
419 ** Values for the scanFlags parameter to vfile_scan().
420 */
421 #define SCAN_ALL 0x001 /* Includes files that begin with "." */
422 #define SCAN_TEMP 0x002 /* Only Fossil-generated files like *-baseline */
423 #define SCAN_NESTED 0x004 /* Scan for empty dirs in nested checkouts */
424 #endif /* INTERFACE */
425
426 /*
427 ** Load into table SFILE the name of every ordinary file in
428 ** the directory pPath. Omit the first nPrefix characters of
@@ -593,11 +594,11 @@
594 if( glob_match(pIgnore1, &zPath[nPrefix+1]) ||
595 glob_match(pIgnore2, &zPath[nPrefix+1]) ||
596 glob_match(pIgnore3, &zPath[nPrefix+1]) ){
597 /* do nothing */
598 }else if( file_wd_isdir(zPath)==1 ){
599 if( (scanFlags & SCAN_NESTED) || !vfile_top_of_checkout(zPath) ){
600 Blob dirPattern;
601 int count = vfile_dir_scan(pPath, nPrefix, scanFlags, pIgnore1,
602 pIgnore2, pIgnore3);
603 blob_init(&dirPattern, &zPath[nPrefix+1], -1);
604 blob_appendf(&dirPattern, "*");
605

Keyboard Shortcuts

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