action is to include empty directories in any copy and move action. It makes a lot more sense for Move, and seems reasonable for Copy. Fixed up Move to correctly remove the original directories rather than leave them behind. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@268068 13f79535-47bb-0310-9956-ffa450edef68master
@@ -82,8 +82,10 @@ public class Copy extends Task { | |||
protected boolean forceOverwrite = false; | |||
protected boolean flatten = false; | |||
protected int verbosity = Project.MSG_VERBOSE; | |||
protected boolean includeEmpty = true; | |||
protected Hashtable fileCopyMap = new Hashtable(); | |||
protected Hashtable dirCopyMap = new Hashtable(); | |||
/** | |||
* Sets a single source file to copy. | |||
@@ -142,6 +144,13 @@ public class Copy extends Task { | |||
} | |||
} | |||
/** | |||
* Used to copy empty directories. | |||
*/ | |||
public void setIncludeEmptyDirs(boolean includeEmpty) { | |||
this.includeEmpty = includeEmpty; | |||
} | |||
/** | |||
* Adds a set of files (nested fileset attribute). | |||
*/ | |||
@@ -172,9 +181,12 @@ public class Copy extends Task { | |||
for (int i=0; i<filesets.size(); i++) { | |||
FileSet fs = (FileSet) filesets.elementAt(i); | |||
DirectoryScanner ds = fs.getDirectoryScanner(project); | |||
File fromDir = fs.getDir(project); | |||
String[] srcFiles = ds.getIncludedFiles(); | |||
scan(fs.getDir(project), destDir, srcFiles); // add to fileCopyMap | |||
String[] srcDirs = ds.getIncludedDirectories(); | |||
scan(fromDir, destDir, srcFiles, srcDirs); | |||
} | |||
// do all the copy operations now... | |||
@@ -206,7 +218,7 @@ public class Copy extends Task { | |||
if (file != null && file.exists() && file.isDirectory()) { | |||
throw new BuildException("Use a fileset to copy directories."); | |||
} | |||
if (destFile != null && filesets.size() > 0) { | |||
throw new BuildException("Cannot concatenate multple files into a single file."); | |||
} | |||
@@ -221,7 +233,7 @@ public class Copy extends Task { | |||
* Compares source files to destination files to see if they should be | |||
* copied. | |||
*/ | |||
protected void scan(File fromDir, File toDir, String[] files) { | |||
protected void scan(File fromDir, File toDir, String[] files, String[] dirs) { | |||
for (int i = 0; i < files.length; i++) { | |||
String filename = files[i]; | |||
File src = new File(fromDir, filename); | |||
@@ -237,8 +249,28 @@ public class Copy extends Task { | |||
dest.getAbsolutePath()); | |||
} | |||
} | |||
if (includeEmpty) { | |||
for (int i = 0; i < dirs.length; i++) { | |||
String dname = dirs[i]; | |||
File sd = new File(fromDir, dname); | |||
File dd; | |||
if (flatten) { | |||
dd = new File(toDir, new File(dname).getName()); | |||
} else { | |||
dd = new File(toDir, dname); | |||
} | |||
if (forceOverwrite || (sd.lastModified() > dd.lastModified())) { | |||
dirCopyMap.put(sd.getAbsolutePath(), dd.getAbsolutePath()); | |||
} | |||
} | |||
} | |||
} | |||
/** | |||
* Actually does the file (and possibly empty directory) copies. | |||
* This is a good method for subclasses to override. | |||
*/ | |||
protected void doFileOperations() { | |||
if (fileCopyMap.size() > 0) { | |||
log("Copying " + fileCopyMap.size() + " files to " + | |||
@@ -262,6 +294,25 @@ public class Copy extends Task { | |||
} | |||
} | |||
} | |||
if (includeEmpty) { | |||
Enumeration e = dirCopyMap.elements(); | |||
int count = 0; | |||
while (e.hasMoreElements()) { | |||
File d = new File((String)e.nextElement()); | |||
if (!d.exists()) { | |||
if (!d.mkdirs()) { | |||
log("Unable to create directory " + d.getAbsolutePath(), Project.MSG_ERR); | |||
} else { | |||
count++; | |||
} | |||
} | |||
} | |||
if (count > 0) { | |||
log("Copied " + count + " empty directories to " + destDir.getAbsolutePath()); | |||
} | |||
} | |||
} | |||
} |
@@ -84,16 +84,12 @@ public class Move extends Copy { | |||
forceOverwrite = true; | |||
} | |||
public void execute() throws BuildException { | |||
super.execute(); | |||
} | |||
//************************************************************************ | |||
// protected and private methods | |||
//************************************************************************ | |||
protected void doFileOperations() { | |||
if (fileCopyMap.size() > 0) { | |||
if (fileCopyMap.size() > 0) { // files to move | |||
log("Moving " + fileCopyMap.size() + " files to " + | |||
destDir.getAbsolutePath() ); | |||
@@ -104,10 +100,7 @@ public class Move extends Copy { | |||
try { | |||
log("Moving " + fromFile + " to " + toFile, verbosity); | |||
project.copyFile(fromFile, | |||
toFile, | |||
filtering, | |||
forceOverwrite); | |||
project.copyFile(fromFile, toFile, filtering, forceOverwrite); | |||
File f = new File(fromFile); | |||
if (!f.delete()) { | |||
throw new BuildException("Unable to delete file " + f.getAbsolutePath()); | |||
@@ -119,10 +112,67 @@ public class Move extends Copy { | |||
} | |||
} | |||
} | |||
if (includeEmpty) { | |||
Enumeration e = dirCopyMap.elements(); | |||
int count = 0; | |||
while (e.hasMoreElements()) { | |||
File d = new File((String)e.nextElement()); | |||
if (!d.exists()) { | |||
if (!d.mkdirs()) { | |||
log("Unable to create directory " + d.getAbsolutePath(), Project.MSG_ERR); | |||
} else { | |||
count++; | |||
} | |||
} | |||
} | |||
if (count > 0) { | |||
log("Moved " + count + " empty directories to " + destDir.getAbsolutePath()); | |||
} | |||
} | |||
if (filesets.size() > 0) { | |||
Enumeration e = filesets.elements(); | |||
while (e.hasMoreElements()) { | |||
FileSet fs = (FileSet)e.nextElement(); | |||
File dir = fs.getDir(project); | |||
if (okToDelete(dir)) { | |||
deleteDir(dir); | |||
} | |||
} | |||
} | |||
} | |||
/** | |||
* Its only ok to delete a directory tree if there are | |||
* no files in it. | |||
*/ | |||
protected boolean okToDelete(File d) { | |||
String[] list = d.list(); | |||
if (list == null) return false; // maybe io error? | |||
for (int i = 0; i < list.length; i++) { | |||
String s = list[i]; | |||
File f = new File(d, s); | |||
if (f.isDirectory()) { | |||
if (!okToDelete(f)) return false; | |||
} else { | |||
return false; // found a file | |||
} | |||
} | |||
return true; | |||
} | |||
/** | |||
* Go and delete the directory tree. | |||
*/ | |||
protected void deleteDir(File d) { | |||
String[] list = d.list(); | |||
String[] list = d.list(); | |||
if (list == null) return; // on an io error list() can return null | |||
for (int i = 0; i < list.length; i++) { | |||
String s = list[i]; | |||
File f = new File(d, s); | |||
@@ -134,8 +184,8 @@ public class Move extends Copy { | |||
} | |||
log("Deleting directory " + d.getAbsolutePath(), verbosity); | |||
if (!d.delete()) { | |||
throw new BuildException("Unable to delete directory " + d.getAbsolutePath()); | |||
} | |||
throw new BuildException("Unable to delete directory " + d.getAbsolutePath()); | |||
} | |||
} | |||
} |