Clover coverage report - Ant Coverage
Coverage timestamp: Tue Apr 8 2003 20:43:55 EST
file stats: LOC: 616   Methods: 36
NCLOC: 327   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
Delete.java 47% 32.4% 22.2% 34.8%
 1   
 /*
 2   
  * The Apache Software License, Version 1.1
 3   
  *
 4   
  * Copyright (c) 2000-2002 The Apache Software Foundation.  All rights 
 5   
  * reserved.
 6   
  *
 7   
  * Redistribution and use in source and binary forms, with or without
 8   
  * modification, are permitted provided that the following conditions
 9   
  * are met:
 10   
  *
 11   
  * 1. Redistributions of source code must retain the above copyright
 12   
  *    notice, this list of conditions and the following disclaimer.
 13   
  *
 14   
  * 2. Redistributions in binary form must reproduce the above copyright
 15   
  *    notice, this list of conditions and the following disclaimer in
 16   
  *    the documentation and/or other materials provided with the
 17   
  *    distribution.
 18   
  *
 19   
  * 3. The end-user documentation included with the redistribution, if
 20   
  *    any, must include the following acknowlegement:
 21   
  *       "This product includes software developed by the
 22   
  *        Apache Software Foundation (http://www.apache.org/)."
 23   
  *    Alternately, this acknowlegement may appear in the software itself,
 24   
  *    if and wherever such third-party acknowlegements normally appear.
 25   
  *
 26   
  * 4. The names "Ant" and "Apache Software
 27   
  *    Foundation" must not be used to endorse or promote products derived
 28   
  *    from this software without prior written permission. For written
 29   
  *    permission, please contact apache@apache.org.
 30   
  *
 31   
  * 5. Products derived from this software may not be called "Apache"
 32   
  *    nor may "Apache" appear in their names without prior written
 33   
  *    permission of the Apache Group.
 34   
  *
 35   
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 36   
  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 37   
  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 38   
  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 39   
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 40   
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 41   
  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 42   
  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 43   
  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 44   
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 45   
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 46   
  * SUCH DAMAGE.
 47   
  * ====================================================================
 48   
  *
 49   
  * This software consists of voluntary contributions made by many
 50   
  * individuals on behalf of the Apache Software Foundation.  For more
 51   
  * information on the Apache Software Foundation, please see
 52   
  * <http://www.apache.org/>.
 53   
  */
 54   
 
 55   
 package org.apache.tools.ant.taskdefs;
 56   
 
 57   
 import java.io.File;
 58   
 import java.util.Vector;
 59   
 import org.apache.tools.ant.BuildException;
 60   
 import org.apache.tools.ant.DirectoryScanner;
 61   
 import org.apache.tools.ant.Project;
 62   
 import org.apache.tools.ant.types.FileSet;
 63   
 import org.apache.tools.ant.types.PatternSet;
 64   
 import org.apache.tools.ant.types.selectors.AndSelector;
 65   
 import org.apache.tools.ant.types.selectors.ContainsSelector;
 66   
 import org.apache.tools.ant.types.selectors.DateSelector;
 67   
 import org.apache.tools.ant.types.selectors.DependSelector;
 68   
 import org.apache.tools.ant.types.selectors.DepthSelector;
 69   
 import org.apache.tools.ant.types.selectors.ExtendSelector;
 70   
 import org.apache.tools.ant.types.selectors.FileSelector;
 71   
 import org.apache.tools.ant.types.selectors.FilenameSelector;
 72   
 import org.apache.tools.ant.types.selectors.MajoritySelector;
 73   
 import org.apache.tools.ant.types.selectors.NoneSelector;
 74   
 import org.apache.tools.ant.types.selectors.NotSelector;
 75   
 import org.apache.tools.ant.types.selectors.OrSelector;
 76   
 import org.apache.tools.ant.types.selectors.PresentSelector;
 77   
 import org.apache.tools.ant.types.selectors.SelectSelector;
 78   
 import org.apache.tools.ant.types.selectors.SelectorContainer;
 79   
 import org.apache.tools.ant.types.selectors.SizeSelector;
 80   
 
 81   
 /**
 82   
  * Deletes a file or directory, or set of files defined by a fileset.
 83   
  * The original delete task would delete a file, or a set of files 
 84   
  * using the include/exclude syntax.  The deltree task would delete a 
 85   
  * directory tree.  This task combines the functionality of these two
 86   
  * originally distinct tasks.
 87   
  * <p>Currently Delete extends MatchingTask.  This is intend <i>only</i>
 88   
  * to provide backwards compatibility for a release.  The future position
 89   
  * is to use nested filesets exclusively.</p>
 90   
  * 
 91   
  * @author Stefano Mazzocchi 
 92   
  *         <a href="mailto:stefano@apache.org">stefano@apache.org</a>
 93   
  * @author Tom Dimock <a href="mailto:tad1@cornell.edu">tad1@cornell.edu</a>
 94   
  * @author Glenn McAllister 
 95   
  *         <a href="mailto:glennm@ca.ibm.com">glennm@ca.ibm.com</a>
 96   
  * @author Jon S. Stevens <a href="mailto:jon@latchkey.com">jon@latchkey.com</a>
 97   
  *
 98   
  * @since Ant 1.2
 99   
  *
 100   
  * @ant.task category="filesystem"
 101   
  */
 102   
 public class Delete extends MatchingTask {
 103   
     protected File file = null;
 104   
     protected File dir = null;
 105   
     protected Vector filesets = new Vector();
 106   
     protected boolean usedMatchingTask = false;
 107   
     // by default, remove matching empty dirs
 108   
     protected boolean includeEmpty = false;
 109   
 
 110   
     private int verbosity = Project.MSG_VERBOSE;
 111   
     private boolean quiet = false;
 112   
     private boolean failonerror = true;
 113   
 
 114   
     /**
 115   
      * Set the name of a single file to be removed.
 116   
      *
 117   
      * @param file the file to be deleted
 118   
      */
 119  961
     public void setFile(File file) {
 120  961
         this.file = file;
 121   
     }
 122   
 
 123   
     /**
 124   
      * Set the directory from which files are to be deleted
 125   
      *
 126   
      * @param dir the directory path.
 127   
      */
 128  266
     public void setDir(File dir) {
 129  266
         this.dir = dir;
 130   
     }
 131   
 
 132   
     /**
 133   
      * If true, list all names of deleted files.
 134   
      *
 135   
      * @param verbose "true" or "on"
 136   
      */
 137  0
     public void setVerbose(boolean verbose) {
 138  0
         if (verbose) {
 139  0
             this.verbosity = Project.MSG_INFO;
 140   
         } else {
 141  0
             this.verbosity = Project.MSG_VERBOSE;
 142   
         }
 143   
     }
 144   
 
 145   
     /**
 146   
      * If true and the file does not exist, do not display a diagnostic
 147   
      * message or modify the exit status to reflect an error.
 148   
      * This means that if a file or directory cannot be deleted,
 149   
      * then no error is reported. This setting emulates the
 150   
      * -f option to the Unix &quot;rm&quot; command.
 151   
      * Default is false meaning things are &quot;noisy&quot;
 152   
      * @param quiet "true" or "on"
 153   
      */
 154  26
     public void setQuiet(boolean quiet) {
 155  26
         this.quiet = quiet;
 156  26
         if (quiet) {
 157  26
             this.failonerror = false;
 158   
         }
 159   
     }
 160   
 
 161   
     /**
 162   
      * If false, note errors but continue.
 163   
      *
 164   
      * @param failonerror true or false
 165   
      */
 166  36
      public void setFailOnError(boolean failonerror) {
 167  36
          this.failonerror = failonerror;
 168   
      }
 169   
 
 170   
 
 171   
     /**
 172   
      * If true, delete empty directories.
 173   
      */
 174  0
     public void setIncludeEmptyDirs(boolean includeEmpty) {
 175  0
         this.includeEmpty = includeEmpty;
 176   
     }
 177   
 
 178   
    /**
 179   
      * Adds a set of files to be deleted.
 180   
      */
 181  20
     public void addFileset(FileSet set) {
 182  20
         filesets.addElement(set);
 183   
     }
 184   
 
 185   
     /**
 186   
      * add a name entry on the include list
 187   
      */
 188  0
     public PatternSet.NameEntry createInclude() {
 189  0
         usedMatchingTask = true;
 190  0
         return super.createInclude();
 191   
     }
 192   
 
 193   
     /**
 194   
      * add a name entry on the include files list
 195   
      */
 196  0
     public PatternSet.NameEntry createIncludesFile() {
 197  0
         usedMatchingTask = true;
 198  0
         return super.createIncludesFile();
 199   
     }
 200   
     
 201   
     /**
 202   
      * add a name entry on the exclude list
 203   
      */
 204  0
     public PatternSet.NameEntry createExclude() {
 205  0
         usedMatchingTask = true;
 206  0
         return super.createExclude();
 207   
     }
 208   
 
 209   
     /**
 210   
      * add a name entry on the include files list
 211   
      */
 212  0
     public PatternSet.NameEntry createExcludesFile() {
 213  0
         usedMatchingTask = true;
 214  0
         return super.createExcludesFile();
 215   
     }
 216   
     
 217   
     /**
 218   
      * add a set of patterns
 219   
      */
 220  0
     public PatternSet createPatternSet() {
 221  0
         usedMatchingTask = true;
 222  0
         return super.createPatternSet();
 223   
     }
 224   
 
 225   
     /**
 226   
      * Sets the set of include patterns. Patterns may be separated by a comma
 227   
      * or a space.
 228   
      *
 229   
      * @param includes the string containing the include patterns
 230   
      */
 231  0
     public void setIncludes(String includes) {
 232  0
         usedMatchingTask = true;
 233  0
         super.setIncludes(includes);
 234   
     }
 235   
 
 236   
     /**
 237   
      * Sets the set of exclude patterns. Patterns may be separated by a comma
 238   
      * or a space.
 239   
      *
 240   
      * @param excludes the string containing the exclude patterns
 241   
      */
 242  0
     public void setExcludes(String excludes) {
 243  0
         usedMatchingTask = true;
 244  0
         super.setExcludes(excludes);
 245   
     }
 246   
 
 247   
     /**
 248   
      * Sets whether default exclusions should be used or not.
 249   
      *
 250   
      * @param useDefaultExcludes "true"|"on"|"yes" when default exclusions
 251   
      *                           should be used, "false"|"off"|"no" when they
 252   
      *                           shouldn't be used.
 253   
      */
 254  0
     public void setDefaultexcludes(boolean useDefaultExcludes) {
 255  0
         usedMatchingTask = true;
 256  0
         super.setDefaultexcludes(useDefaultExcludes);
 257   
     }
 258   
 
 259   
     /**
 260   
      * Sets the name of the file containing the includes patterns.
 261   
      *
 262   
      * @param includesfile A string containing the filename to fetch
 263   
      * the include patterns from.
 264   
      */
 265  0
     public void setIncludesfile(File includesfile) {
 266  0
         usedMatchingTask = true;
 267  0
         super.setIncludesfile(includesfile);
 268   
     }
 269   
 
 270   
     /**
 271   
      * Sets the name of the file containing the includes patterns.
 272   
      *
 273   
      * @param excludesfile A string containing the filename to fetch
 274   
      * the include patterns from.
 275   
      */
 276  0
     public void setExcludesfile(File excludesfile) {
 277  0
         usedMatchingTask = true;
 278  0
         super.setExcludesfile(excludesfile);
 279   
     }
 280   
 
 281   
     /**
 282   
      * Sets case sensitivity of the file system
 283   
      *
 284   
      * @param isCaseSensitive "true"|"on"|"yes" if file system is case
 285   
      *                           sensitive, "false"|"off"|"no" when not.
 286   
      */
 287  0
     public void setCaseSensitive(boolean isCaseSensitive) {
 288  0
         usedMatchingTask = true;
 289  0
         super.setCaseSensitive(isCaseSensitive);
 290   
     }
 291   
 
 292   
     /**
 293   
      * Sets whether or not symbolic links should be followed.
 294   
      *
 295   
      * @param followSymlinks whether or not symbolic links should be followed
 296   
      */
 297  0
     public void setFollowSymlinks(boolean followSymlinks) {
 298  0
         usedMatchingTask = true;
 299  0
         super.setFollowSymlinks(followSymlinks);
 300   
     }
 301   
 
 302   
     /**
 303   
      * add a "Select" selector entry on the selector list
 304   
      */
 305  0
     public void addSelector(SelectSelector selector) {
 306  0
         usedMatchingTask = true;
 307  0
         super.addSelector(selector);
 308   
     }
 309   
 
 310   
     /**
 311   
      * add an "And" selector entry on the selector list
 312   
      */
 313  0
     public void addAnd(AndSelector selector) {
 314  0
         usedMatchingTask = true;
 315  0
         super.addAnd(selector);
 316   
     }
 317   
 
 318   
     /**
 319   
      * add an "Or" selector entry on the selector list
 320   
      */
 321  0
     public void addOr(OrSelector selector) {
 322  0
         usedMatchingTask = true;
 323  0
         super.addOr(selector);
 324   
     }
 325   
 
 326   
     /**
 327   
      * add a "Not" selector entry on the selector list
 328   
      */
 329  0
     public void addNot(NotSelector selector) {
 330  0
         usedMatchingTask = true;
 331  0
         super.addNot(selector);
 332   
     }
 333   
 
 334   
     /**
 335   
      * add a "None" selector entry on the selector list
 336   
      */
 337  0
     public void addNone(NoneSelector selector) {
 338  0
         usedMatchingTask = true;
 339  0
         super.addNone(selector);
 340   
     }
 341   
 
 342   
     /**
 343   
      * add a majority selector entry on the selector list
 344   
      */
 345  0
     public void addMajority(MajoritySelector selector) {
 346  0
         usedMatchingTask = true;
 347  0
         super.addMajority(selector);
 348   
     }
 349   
 
 350   
     /**
 351   
      * add a selector date entry on the selector list
 352   
      */
 353  0
     public void addDate(DateSelector selector) {
 354  0
         usedMatchingTask = true;
 355  0
         super.addDate(selector);
 356   
     }
 357   
 
 358   
     /**
 359   
      * add a selector size entry on the selector list
 360   
      */
 361  0
     public void addSize(SizeSelector selector) {
 362  0
         usedMatchingTask = true;
 363  0
         super.addSize(selector);
 364   
     }
 365   
 
 366   
     /**
 367   
      * add a selector filename entry on the selector list
 368   
      */
 369  0
     public void addFilename(FilenameSelector selector) {
 370  0
         usedMatchingTask = true;
 371  0
         super.addFilename(selector);
 372   
     }
 373   
 
 374   
     /**
 375   
      * add an extended selector entry on the selector list
 376   
      */
 377  0
     public void addCustom(ExtendSelector selector) {
 378  0
         usedMatchingTask = true;
 379  0
         super.addCustom(selector);
 380   
     }
 381   
 
 382   
     /**
 383   
      * add a contains selector entry on the selector list
 384   
      */
 385  0
     public void addContains(ContainsSelector selector) {
 386  0
         usedMatchingTask = true;
 387  0
         super.addContains(selector);
 388   
     }
 389   
 
 390   
     /**
 391   
      * add a present selector entry on the selector list
 392   
      */
 393  0
     public void addPresent(PresentSelector selector) {
 394  0
         usedMatchingTask = true;
 395  0
         super.addPresent(selector);
 396   
     }
 397   
 
 398   
     /**
 399   
      * add a depth selector entry on the selector list
 400   
      */
 401  0
     public void addDepth(DepthSelector selector) {
 402  0
         usedMatchingTask = true;
 403  0
         super.addDepth(selector);
 404   
     }
 405   
 
 406   
     /**
 407   
      * add a depends selector entry on the selector list
 408   
      */
 409  0
     public void addDepend(DependSelector selector) {
 410  0
         usedMatchingTask = true;
 411  0
         super.addDepend(selector);
 412   
     }
 413   
 
 414   
     /**
 415   
      * Delete the file(s).
 416   
      */
 417  1276
     public void execute() throws BuildException {
 418  1276
         if (usedMatchingTask) {
 419  0
             log("DEPRECATED - Use of the implicit FileSet is deprecated.  "
 420   
                 + "Use a nested fileset element instead.");
 421   
         }
 422   
 
 423  1276
         if (file == null && dir == null && filesets.size() == 0) {
 424  1
             throw new BuildException("At least one of the file or dir "
 425   
                                      + "attributes, or a fileset element, "
 426   
                                      + "must be set.");
 427   
         }
 428   
 
 429  1275
         if (quiet && failonerror) {
 430  0
             throw new BuildException("quiet and failonerror cannot both be "
 431   
                                      + "set to true", getLocation());
 432   
         }
 433   
         
 434   
 
 435   
         // delete the single file
 436  1275
         if (file != null) {
 437  961
             if (file.exists()) {
 438  155
                 if (file.isDirectory()) {
 439  1
                     log("Directory " + file.getAbsolutePath() 
 440   
                         + " cannot be removed using the file attribute.  "
 441   
                         + "Use dir instead.");
 442   
                 } else {
 443  154
                     log("Deleting: " + file.getAbsolutePath());
 444   
 
 445  154
                     if (!file.delete()) {
 446  0
                         String message = "Unable to delete file " 
 447   
                             + file.getAbsolutePath();
 448  0
                         if (failonerror) {
 449  0
                             throw new BuildException(message);
 450   
                         } else { 
 451  0
                             log(message, quiet ? Project.MSG_VERBOSE 
 452   
                                                : Project.MSG_WARN);
 453   
                         }
 454   
                     }
 455   
                 }
 456   
             } else {
 457  806
                 log("Could not find file " + file.getAbsolutePath() 
 458   
                     + " to delete.", 
 459   
                     Project.MSG_VERBOSE);
 460   
             }
 461   
         }
 462   
 
 463   
         // delete the directory
 464  1275
         if (dir != null && dir.exists() && dir.isDirectory() && 
 465   
             !usedMatchingTask) {
 466   
             /*
 467   
                If verbosity is MSG_VERBOSE, that mean we are doing
 468   
                regular logging (backwards as that sounds).  In that
 469   
                case, we want to print one message about deleting the
 470   
                top of the directory tree.  Otherwise, the removeDir
 471   
                method will handle messages for _all_ directories.
 472   
              */
 473  105
             if (verbosity == Project.MSG_VERBOSE) {
 474  105
                 log("Deleting directory " + dir.getAbsolutePath());
 475   
             }
 476  105
             removeDir(dir);
 477   
         }
 478   
 
 479   
         // delete the files in the filesets
 480  1275
         for (int i = 0; i < filesets.size(); i++) {
 481  20
             FileSet fs = (FileSet) filesets.elementAt(i);
 482  20
             try {
 483  20
                 DirectoryScanner ds = fs.getDirectoryScanner(getProject());
 484  20
                 String[] files = ds.getIncludedFiles();
 485  20
                 String[] dirs = ds.getIncludedDirectories();
 486  20
                 removeFiles(fs.getDir(getProject()), files, dirs);
 487   
             } catch (BuildException be) {
 488   
                 // directory doesn't exist or is not readable
 489  0
                 if (failonerror) {
 490  0
                     throw be;
 491   
                 } else {
 492  0
                     log(be.getMessage(), 
 493   
                         quiet ? Project.MSG_VERBOSE : Project.MSG_WARN);
 494   
                 }
 495   
             }
 496   
         }
 497   
 
 498   
         // delete the files from the default fileset
 499  1275
         if (usedMatchingTask && dir != null) {
 500  0
             try {
 501  0
                 DirectoryScanner ds = super.getDirectoryScanner(dir);
 502  0
                 String[] files = ds.getIncludedFiles();
 503  0
                 String[] dirs = ds.getIncludedDirectories();
 504  0
                 removeFiles(dir, files, dirs);
 505   
             } catch (BuildException be) {
 506   
                 // directory doesn't exist or is not readable
 507  0
                 if (failonerror) {
 508  0
                     throw be;
 509   
                 } else {
 510  0
                     log(be.getMessage(), 
 511   
                         quiet ? Project.MSG_VERBOSE : Project.MSG_WARN);
 512   
                 }
 513   
             }
 514   
         }
 515   
     }
 516   
 
 517   
 //************************************************************************
 518   
 //  protected and private methods
 519   
 //************************************************************************
 520   
 
 521  296
     protected void removeDir(File d) {
 522  296
         String[] list = d.list();
 523  296
         if (list == null) {
 524  0
             list = new String[0];
 525   
         }
 526  296
         for (int i = 0; i < list.length; i++) {
 527  1314
             String s = list[i];
 528  1314
             File f = new File(d, s);
 529  1314
             if (f.isDirectory()) {
 530  191
                 removeDir(f);
 531   
             } else {
 532  1123
                 log("Deleting " + f.getAbsolutePath(), verbosity);
 533  1123
                 if (!f.delete()) {
 534  0
                     String message = "Unable to delete file " 
 535   
                         + f.getAbsolutePath();
 536  0
                     if (failonerror) {
 537  0
                         throw new BuildException(message);
 538   
                     } else {
 539  0
                         log(message,
 540   
                             quiet ? Project.MSG_VERBOSE : Project.MSG_WARN);
 541   
                     }
 542   
                 }
 543   
             }
 544   
         }
 545  296
         log("Deleting directory " + d.getAbsolutePath(), verbosity);
 546  296
         if (!d.delete()) {
 547  0
             String message = "Unable to delete directory " 
 548   
                 + dir.getAbsolutePath();
 549  0
             if (failonerror) {
 550  0
                 throw new BuildException(message);
 551   
             } else {
 552  0
                 log(message,
 553   
                     quiet ? Project.MSG_VERBOSE : Project.MSG_WARN);
 554   
             }
 555   
         }
 556   
     }
 557   
 
 558   
     /**
 559   
      * remove an array of files in a directory, and a list of subdirectories
 560   
      * which will only be deleted if 'includeEmpty' is true
 561   
      * @param d directory to work from
 562   
      * @param files array of files to delete; can be of zero length
 563   
      * @param dirs array of directories to delete; can of zero length
 564   
      */
 565  20
     protected void removeFiles(File d, String[] files, String[] dirs) {
 566  20
         if (files.length > 0) {
 567  14
             log("Deleting " + files.length + " files from " 
 568   
                 + d.getAbsolutePath());
 569  14
             for (int j = 0; j < files.length; j++) {
 570  15
                 File f = new File(d, files[j]);
 571  15
                 log("Deleting " + f.getAbsolutePath(), verbosity);
 572  15
                 if (!f.delete()) {
 573  0
                     String message = "Unable to delete file " 
 574   
                         + f.getAbsolutePath();
 575  0
                     if (failonerror) {
 576  0
                         throw new BuildException(message);
 577   
                     } else {
 578  0
                         log(message,
 579   
                             quiet ? Project.MSG_VERBOSE : Project.MSG_WARN);
 580   
                     }
 581   
                 }
 582   
             }
 583   
         }
 584   
 
 585  20
         if (dirs.length > 0 && includeEmpty) {
 586  0
             int dirCount = 0;
 587  0
             for (int j = dirs.length - 1; j >= 0; j--) {
 588  0
                 File dir = new File(d, dirs[j]);
 589  0
                 String[] dirFiles = dir.list();
 590  0
                 if (dirFiles == null || dirFiles.length == 0) {
 591  0
                     log("Deleting " + dir.getAbsolutePath(), verbosity);
 592  0
                     if (!dir.delete()) {
 593  0
                         String message = "Unable to delete directory "
 594   
                                 + dir.getAbsolutePath();
 595  0
                         if (failonerror) {
 596  0
                             throw new BuildException(message);
 597   
                         } else {
 598  0
                             log(message,
 599   
                                 quiet ? Project.MSG_VERBOSE : Project.MSG_WARN);
 600   
                         }
 601   
                     } else {
 602  0
                         dirCount++;
 603   
                     }
 604   
                 }
 605   
             }
 606   
 
 607  0
             if (dirCount > 0) {
 608  0
                 log("Deleted " + dirCount + " director" +
 609   
                     (dirCount == 1 ? "y" : "ies") +
 610   
                     " from " + d.getAbsolutePath());
 611   
             }
 612   
         }
 613   
     }
 614   
 }
 615   
 
 616