into existing directories. PR: 31031 git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@276925 13f79535-47bb-0310-9956-ffa450edef68master
@@ -59,38 +59,129 @@ | |||||
</move> | </move> | ||||
</target> | </target> | ||||
<target name="testCompleteDirectoryMoveFileToFile"> | |||||
<mkdir dir="A"/> | |||||
<touch file="A/1"/> | |||||
<move file="A" tofile="E" /> | |||||
<fail message="E/1 not available"> | |||||
<target name="testMoveFileAndFileset"> | |||||
<mkdir dir="A" /> | |||||
<touch> | |||||
<filelist dir="A" files="1,2,3" /> | |||||
</touch> | |||||
<move todir="E" file="A/1"> | |||||
<fileset dir="A" includes="2,3" /> | |||||
</move> | |||||
<fail message="A unavailable"> | |||||
<condition> | <condition> | ||||
<not> | <not> | ||||
<available file="E/1" type="file" /> | |||||
<available file="A" type="dir" /> | |||||
</not> | </not> | ||||
</condition> | </condition> | ||||
</fail> | </fail> | ||||
<fail message="A remains"> | |||||
<fail message="A/1 not moved"> | |||||
<condition> | |||||
<or> | |||||
<available file="A/1" type="file" /> | |||||
<not> | |||||
<available file="E/1" type="file" /> | |||||
</not> | |||||
</or> | |||||
</condition> | |||||
</fail> | |||||
<fail message="A/2 not moved"> | |||||
<condition> | |||||
<or> | |||||
<available file="A/2" type="file" /> | |||||
<not> | |||||
<available file="E/2" type="file" /> | |||||
</not> | |||||
</or> | |||||
</condition> | |||||
</fail> | |||||
<fail message="A/3 not moved"> | |||||
<condition> | |||||
<or> | |||||
<available file="A/3" type="file" /> | |||||
<not> | |||||
<available file="E/3" type="file" /> | |||||
</not> | |||||
</or> | |||||
</condition> | |||||
</fail> | |||||
</target> | |||||
<macrodef name="verifymove"> | |||||
<attribute name="newfile" /> | |||||
<attribute name="olddir" /> | |||||
<sequential> | |||||
<fail message="@{newfile} not available"> | |||||
<condition> | |||||
<not> | |||||
<available file="@{newfile}" type="file" /> | |||||
</not> | |||||
</condition> | |||||
</fail> | |||||
<fail message="@{olddir} remains"> | |||||
<condition> | |||||
<available file="@{olddir}" type="dir" /> | |||||
</condition> | |||||
</fail> | |||||
</sequential> | |||||
</macrodef> | |||||
<target name="testCompleteDirectoryMoveToExistingDir"> | |||||
<mkdir dir="A" /> | |||||
<touch file="A/1" /> | |||||
<mkdir dir="E" /> | |||||
<touch file="E/2" /> | |||||
<move todir="E"> | |||||
<fileset dir="A" /> | |||||
</move> | |||||
<verifymove newfile="E/1" olddir="A" /> | |||||
<fail message="E/2 unavailable"> | |||||
<condition> | <condition> | ||||
<available file="A" type="dir" /> | |||||
<not> | |||||
<available file="E/2" type="file" /> | |||||
</not> | |||||
</condition> | </condition> | ||||
</fail> | </fail> | ||||
</target> | </target> | ||||
<target name="testCompleteDirectoryMoveFileToFile"> | |||||
<mkdir dir="A"/> | |||||
<touch file="A/1"/> | |||||
<move file="A" tofile="E" /> | |||||
<verifymove newfile="E/1" olddir="A" /> | |||||
</target> | |||||
<target name="testCompleteDirectoryMoveFileToDir"> | <target name="testCompleteDirectoryMoveFileToDir"> | ||||
<mkdir dir="A"/> | <mkdir dir="A"/> | ||||
<touch file="A/1"/> | <touch file="A/1"/> | ||||
<move file="A" todir="E" /> | <move file="A" todir="E" /> | ||||
<fail message="E/A/1 not available"> | |||||
<verifymove newfile="E/A/1" olddir="A" /> | |||||
</target> | |||||
<target name="testCompleteDirectoryMoveFileAndFileset"> | |||||
<mkdir dir="A/1" /> | |||||
<touch file="A/2" /> | |||||
<move file="A/1" todir="E"> | |||||
<fileset dir="A" includes="2" /> | |||||
</move> | |||||
<fail message="A unavailable"> | |||||
<condition> | <condition> | ||||
<not> | <not> | ||||
<available file="E/A/1" type="file" /> | |||||
<available file="A" type="dir" /> | |||||
</not> | </not> | ||||
</condition> | </condition> | ||||
</fail> | </fail> | ||||
<fail message="A remains"> | |||||
<fail message="E/1 unavailable"> | |||||
<condition> | <condition> | ||||
<available file="A" type="dir" /> | |||||
<not> | |||||
<available file="E/1" type="dir" /> | |||||
</not> | |||||
</condition> | |||||
</fail> | |||||
<fail message="E/2 unavailable"> | |||||
<condition> | |||||
<not> | |||||
<available file="E/2" type="file" /> | |||||
</not> | |||||
</condition> | </condition> | ||||
</fail> | </fail> | ||||
</target> | </target> | ||||
@@ -98,8 +189,8 @@ | |||||
<target name="testCompleteDirectoryMoveFileToExistingFile"> | <target name="testCompleteDirectoryMoveFileToExistingFile"> | ||||
<mkdir dir="A"/> | <mkdir dir="A"/> | ||||
<touch file="A/1"/> | <touch file="A/1"/> | ||||
<touch file="B"/> | |||||
<move file="A" tofile="B" /> | |||||
<touch file="E"/> | |||||
<move file="A" tofile="E" /> | |||||
</target> | </target> | ||||
<target name="testCompleteDirectoryMoveFileToExistingDir"> | <target name="testCompleteDirectoryMoveFileToExistingDir"> | ||||
@@ -107,6 +198,7 @@ | |||||
<touch file="A/1"/> | <touch file="A/1"/> | ||||
<mkdir dir="E"/> | <mkdir dir="E"/> | ||||
<move file="A" tofile="E" /> | <move file="A" tofile="E" /> | ||||
<verifymove newfile="E/1" olddir="A" /> | |||||
</target> | </target> | ||||
<target name="testCompleteDirectoryMoveFileToDirWithExistingFile"> | <target name="testCompleteDirectoryMoveFileToDirWithExistingFile"> | ||||
@@ -123,6 +215,7 @@ | |||||
<mkdir dir="E"/> | <mkdir dir="E"/> | ||||
<mkdir dir="E/A"/> | <mkdir dir="E/A"/> | ||||
<move file="A" todir="E" /> | <move file="A" todir="E" /> | ||||
<verifymove newfile="E/A/1" olddir="A" /> | |||||
</target> | </target> | ||||
<target name="cleanup"> | <target name="cleanup"> | ||||
@@ -73,9 +73,9 @@ public class Copy extends Task { | |||||
protected Hashtable completeDirMap = new Hashtable(); | protected Hashtable completeDirMap = new Hashtable(); | ||||
protected Mapper mapperElement = null; | protected Mapper mapperElement = null; | ||||
protected FileUtils fileUtils; | |||||
private Vector filterChains = new Vector(); | private Vector filterChains = new Vector(); | ||||
private Vector filterSets = new Vector(); | private Vector filterSets = new Vector(); | ||||
private FileUtils fileUtils; | |||||
private String inputEncoding = null; | private String inputEncoding = null; | ||||
private String outputEncoding = null; | private String outputEncoding = null; | ||||
private long granularity = 0; | private long granularity = 0; | ||||
@@ -20,8 +20,10 @@ package org.apache.tools.ant.taskdefs; | |||||
import java.io.File; | import java.io.File; | ||||
import java.io.IOException; | import java.io.IOException; | ||||
import java.util.Enumeration; | import java.util.Enumeration; | ||||
import org.apache.tools.ant.BuildException; | |||||
import org.apache.tools.ant.Project; | import org.apache.tools.ant.Project; | ||||
import org.apache.tools.ant.BuildException; | |||||
import org.apache.tools.ant.DirectoryScanner; | |||||
import org.apache.tools.ant.types.FileSet; | |||||
import org.apache.tools.ant.types.FilterSet; | import org.apache.tools.ant.types.FilterSet; | ||||
import org.apache.tools.ant.types.FilterSetCollection; | import org.apache.tools.ant.types.FilterSetCollection; | ||||
@@ -61,55 +63,23 @@ public class Move extends Copy { | |||||
setOverwrite(true); | setOverwrite(true); | ||||
} | } | ||||
/** | |||||
* Performs the move operation. | |||||
*/ | |||||
public void execute() throws BuildException { | |||||
// inherit doc | |||||
protected void validateAttributes() throws BuildException { | |||||
if (file != null && file.isDirectory()) { | if (file != null && file.isDirectory()) { | ||||
if (destFile != null && destDir != null) { | |||||
throw new BuildException("Only one of tofile and todir " | |||||
+ "may be set."); | |||||
if ((destFile != null && destDir != null) | |||||
|| (destFile == null && destDir == null)){ | |||||
throw new BuildException("One and only one of tofile and todir " | |||||
+ "must be set."); | |||||
} | } | ||||
destFile = (destFile == null) | |||||
? new File(destDir, file.getName()) : destFile; | |||||
destDir = (destDir == null) | |||||
? fileUtils.getParentFile(destFile) : destDir; | |||||
if (destFile == null && destDir == null) { | |||||
throw new BuildException("One of tofile or todir must be set."); | |||||
} | |||||
destFile = (destFile != null) | |||||
? destFile : new File(destDir, file.getName()); | |||||
try { | |||||
boolean renamed = false; | |||||
log("Moving directory " + file | |||||
+ " to " + destFile, Project.MSG_INFO); | |||||
try { | |||||
renamed = | |||||
renameFile(file, destFile, filtering, forceOverwrite); | |||||
} catch (IOException eyeOhEx) { | |||||
throw new BuildException(eyeOhEx.getMessage()); | |||||
} | |||||
if (!renamed) { | |||||
StringBuffer buf = new StringBuffer( | |||||
"Failed to move directory ").append( | |||||
file.getAbsolutePath()); | |||||
if ((getFilterChains() != null && getFilterChains().size() > 0) | |||||
|| (getFilterSets() != null && getFilterSets().size() > 0) | |||||
|| filtering) { | |||||
buf.append( | |||||
"; use a fileset to move directories with filtering"); | |||||
} | |||||
throw new BuildException(buf.append('.').toString()); | |||||
} | |||||
} catch (BuildException e) { | |||||
if (!failonerror) { | |||||
log("Warning: " + e.getMessage(), Project.MSG_ERR); | |||||
} else { | |||||
throw e; | |||||
} | |||||
} | |||||
completeDirMap.put(file, destFile); | |||||
file = null; | |||||
} else { | } else { | ||||
super.execute(); | |||||
super.validateAttributes(); | |||||
} | } | ||||
} | } | ||||
@@ -128,21 +98,35 @@ public class Move extends Copy { | |||||
while (e.hasMoreElements()) { | while (e.hasMoreElements()) { | ||||
File fromDir = (File) e.nextElement(); | File fromDir = (File) e.nextElement(); | ||||
File toDir = (File) completeDirMap.get(fromDir); | File toDir = (File) completeDirMap.get(fromDir); | ||||
boolean renamed = false; | |||||
try { | try { | ||||
log("Attempting to rename dir: " + fromDir | log("Attempting to rename dir: " + fromDir | ||||
+ " to " + toDir, verbosity); | + " to " + toDir, verbosity); | ||||
renameFile(fromDir, toDir, filtering, forceOverwrite); | |||||
renamed = | |||||
renameFile(fromDir, toDir, filtering, forceOverwrite); | |||||
} catch (IOException ioe) { | } catch (IOException ioe) { | ||||
String msg = "Failed to rename dir " + fromDir | String msg = "Failed to rename dir " + fromDir | ||||
+ " to " + toDir | + " to " + toDir | ||||
+ " due to " + ioe.getMessage(); | + " due to " + ioe.getMessage(); | ||||
throw new BuildException(msg, ioe, getLocation()); | throw new BuildException(msg, ioe, getLocation()); | ||||
} | } | ||||
if (!renamed) { | |||||
FileSet fs = new FileSet(); | |||||
fs.setProject(getProject()); | |||||
fs.setDir(fromDir); | |||||
addFileset(fs); | |||||
DirectoryScanner ds = fs.getDirectoryScanner(getProject()); | |||||
String[] files = ds.getIncludedFiles(); | |||||
String[] dirs = ds.getIncludedDirectories(); | |||||
scan(fromDir, toDir, files, dirs); | |||||
} | |||||
} | } | ||||
} | } | ||||
if (fileCopyMap.size() > 0) { // files to move | |||||
log("Moving " + fileCopyMap.size() + " files to " | |||||
+ destDir.getAbsolutePath()); | |||||
int moveCount = fileCopyMap.size(); | |||||
if (moveCount > 0) { // files to move | |||||
log("Moving " + moveCount + " file" | |||||
+ ((moveCount == 1) ? "" : "s") | |||||
+ " to " + destDir.getAbsolutePath()); | |||||
Enumeration e = fileCopyMap.keys(); | Enumeration e = fileCopyMap.keys(); | ||||
while (e.hasMoreElements()) { | while (e.hasMoreElements()) { | ||||
@@ -325,6 +309,15 @@ public class Move extends Copy { | |||||
* @param d the directory to delete | * @param d the directory to delete | ||||
*/ | */ | ||||
protected void deleteDir(File d) { | protected void deleteDir(File d) { | ||||
deleteDir(d, false); | |||||
} | |||||
/** | |||||
* Go and delete the directory tree. | |||||
* @param d the directory to delete | |||||
* @param deleteFiles whether to delete files | |||||
*/ | |||||
protected void deleteDir(File d, boolean deleteFiles) { | |||||
String[] list = d.list(); | String[] list = d.list(); | ||||
if (list == null) { | if (list == null) { | ||||
return; | return; | ||||
@@ -335,6 +328,9 @@ public class Move extends Copy { | |||||
File f = new File(d, s); | File f = new File(d, s); | ||||
if (f.isDirectory()) { | if (f.isDirectory()) { | ||||
deleteDir(f); | deleteDir(f); | ||||
} else if (deleteFiles && !(f.delete())) { | |||||
throw new BuildException("Unable to delete file " | |||||
+ f.getAbsolutePath()); | |||||
} else { | } else { | ||||
throw new BuildException("UNEXPECTED ERROR - The file " | throw new BuildException("UNEXPECTED ERROR - The file " | ||||
+ f.getAbsolutePath() | + f.getAbsolutePath() | ||||
@@ -370,34 +366,19 @@ public class Move extends Copy { | |||||
boolean filtering, boolean overwrite) | boolean filtering, boolean overwrite) | ||||
throws IOException, BuildException { | throws IOException, BuildException { | ||||
boolean renamed = true; | |||||
if ((getFilterSets() != null && getFilterSets().size() > 0) | |||||
|| (getFilterChains() != null && getFilterChains().size() > 0)) { | |||||
renamed = false; | |||||
} else { | |||||
if (!filtering) { | |||||
// ensure that parent dir of dest file exists! | |||||
File parent = destFile.getParentFile(); | |||||
if (parent != null && !parent.exists()) { | |||||
parent.mkdirs(); | |||||
} | |||||
if (destFile.exists()) { | |||||
if (sourceFile.isDirectory()) { | |||||
throw new BuildException( | |||||
new StringBuffer("Cannot replace ").append( | |||||
((destFile.isFile()) ? "file " : "directory ")).append( | |||||
destFile).append(" with directory ").append( | |||||
sourceFile).toString()); | |||||
} else if (destFile.isFile() && !destFile.delete()) { | |||||
throw new BuildException("Unable to remove existing " | |||||
+ "file " + destFile); | |||||
} | |||||
} | |||||
renamed = sourceFile.renameTo(destFile); | |||||
} else { | |||||
renamed = false; | |||||
boolean renamed = false; | |||||
if ((getFilterSets().size() + getFilterChains().size() == 0) | |||||
&& !(filtering || destFile.isDirectory())) { | |||||
// ensure that parent dir of dest file exists! | |||||
File parent = destFile.getParentFile(); | |||||
if (parent != null && !parent.exists()) { | |||||
parent.mkdirs(); | |||||
} | |||||
if (destFile.isFile() && !destFile.delete()) { | |||||
throw new BuildException("Unable to remove existing " | |||||
+ "file " + destFile); | |||||
} | } | ||||
renamed = sourceFile.renameTo(destFile); | |||||
} | } | ||||
return renamed; | return renamed; | ||||
} | } | ||||
@@ -89,6 +89,14 @@ public class MoveTest extends BuildFileTest { | |||||
assertTrue(!getProject().resolveFile("A").exists()); | assertTrue(!getProject().resolveFile("A").exists()); | ||||
} | } | ||||
public void testMoveFileAndFileset() { | |||||
executeTarget("testMoveFileAndFileset"); | |||||
} | |||||
public void testCompleteDirectoryMoveToExistingDir() { | |||||
executeTarget("testCompleteDirectoryMoveToExistingDir"); | |||||
} | |||||
public void testCompleteDirectoryMoveFileToFile() { | public void testCompleteDirectoryMoveFileToFile() { | ||||
executeTarget("testCompleteDirectoryMoveFileToFile"); | executeTarget("testCompleteDirectoryMoveFileToFile"); | ||||
} | } | ||||
@@ -97,24 +105,24 @@ public class MoveTest extends BuildFileTest { | |||||
executeTarget("testCompleteDirectoryMoveFileToDir"); | executeTarget("testCompleteDirectoryMoveFileToDir"); | ||||
} | } | ||||
public void testCompleteDirectoryMoveFileAndFileset() { | |||||
executeTarget("testCompleteDirectoryMoveFileAndFileset"); | |||||
} | |||||
public void testCompleteDirectoryMoveFileToExistingFile() { | public void testCompleteDirectoryMoveFileToExistingFile() { | ||||
expectBuildExceptionContaining("testCompleteDirectoryMoveFileToExistingFile", | |||||
"", "Cannot replace file"); | |||||
executeTarget("testCompleteDirectoryMoveFileToExistingFile"); | |||||
} | } | ||||
public void testCompleteDirectoryMoveFileToExistingDir() { | public void testCompleteDirectoryMoveFileToExistingDir() { | ||||
expectBuildExceptionContaining("testCompleteDirectoryMoveFileToExistingDir", | |||||
"", "Cannot replace directory"); | |||||
executeTarget("testCompleteDirectoryMoveFileToExistingDir"); | |||||
} | } | ||||
public void testCompleteDirectoryMoveFileToDirWithExistingFile() { | public void testCompleteDirectoryMoveFileToDirWithExistingFile() { | ||||
expectBuildExceptionContaining("testCompleteDirectoryMoveFileToDirWithExistingFile", | |||||
"", "Cannot replace file"); | |||||
executeTarget("testCompleteDirectoryMoveFileToDirWithExistingFile"); | |||||
} | } | ||||
public void testCompleteDirectoryMoveFileToDirWithExistingDir() { | public void testCompleteDirectoryMoveFileToDirWithExistingDir() { | ||||
expectBuildExceptionContaining("testCompleteDirectoryMoveFileToDirWithExistingDir", | |||||
"", "Cannot replace directory"); | |||||
executeTarget("testCompleteDirectoryMoveFileToDirWithExistingDir"); | |||||
} | } | ||||
} | } |