PR: 22863 git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@276806 13f79535-47bb-0310-9956-ffa450edef68master
@@ -42,7 +42,10 @@ Other changes: | |||||
wsdl run on mono, as well as most of the .NET WSE2.0 options. Extra | wsdl run on mono, as well as most of the .NET WSE2.0 options. Extra | ||||
schemas (files or urls) can be named in the <schema> element. | schemas (files or urls) can be named in the <schema> element. | ||||
Compilers can be selected using the compiler attribute, which defaults | Compilers can be selected using the compiler attribute, which defaults | ||||
to "microsoft" on windows, and "mono" on everything else. | |||||
to "microsoft" on windows, and "mono" on everything else. | |||||
* Allow file attribute of <move> to rename a directory. | |||||
Bugzilla Report 22863. | |||||
Changes from Ant 1.6.2 to current Ant 1.6 CVS version | Changes from Ant 1.6.2 to current Ant 1.6 CVS version | ||||
===================================================== | ===================================================== | ||||
@@ -16,6 +16,10 @@ turned off, then files are only moved if the source file is newer than | |||||
the destination file, or when the destination file does not exist.</p> | the destination file, or when the destination file does not exist.</p> | ||||
<p><a href="../CoreTypes/fileset.html">FileSet</a>s are used to select sets of files | <p><a href="../CoreTypes/fileset.html">FileSet</a>s are used to select sets of files | ||||
to move to the <var>todir</var> directory.</p> | to move to the <var>todir</var> directory.</p> | ||||
<p><b>Since Ant 1.6.3</b>, the <i>file</i> attribute may be used to move | |||||
(rename) an entire directory. If <i>tofile</i> denotes an existing file, or | |||||
there is a directory by the same name in <i>todir</i>, the action will fail. | |||||
</p> | |||||
<h3>Parameters</h3> | <h3>Parameters</h3> | ||||
<table border="1" cellpadding="2" cellspacing="0"> | <table border="1" cellpadding="2" cellspacing="0"> | ||||
<tr> | <tr> | ||||
@@ -25,7 +29,7 @@ to move to the <var>todir</var> directory.</p> | |||||
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td valign="top">file</td> | <td valign="top">file</td> | ||||
<td valign="top">the file to move</td> | |||||
<td valign="top">the file or directory to move</td> | |||||
<td valign="top" align="center">One of <var>file</var> or | <td valign="top" align="center">One of <var>file</var> or | ||||
at least one nested fileset element</td> | at least one nested fileset element</td> | ||||
</tr> | </tr> | ||||
@@ -78,7 +82,7 @@ to move to the <var>todir</var> directory.</p> | |||||
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td valign="top">failonerror</td> | <td valign="top">failonerror</td> | ||||
<td valign="top">Log a warning message, but do not stop the | |||||
<td valign="top">If false, log a warning message, but do not stop the | |||||
build, when the file to copy does not exist or one of the nested | build, when the file to copy does not exist or one of the nested | ||||
filesets points to a directory that doesn't exist or an error occurs | filesets points to a directory that doesn't exist or an error occurs | ||||
while moving. | while moving. | ||||
@@ -154,6 +158,10 @@ followed by <filterset> elements. | |||||
<move todir="new/dir/to/move/to"> | <move todir="new/dir/to/move/to"> | ||||
<fileset dir="src/dir"/> | <fileset dir="src/dir"/> | ||||
</move> | </move> | ||||
</pre> | |||||
<i>or, since Ant 1.6.3:</i> | |||||
<pre> | |||||
<move file="src/dir" tofile="new/dir/to/move/to" /> | |||||
</pre> | </pre> | ||||
<p><b>Move a set of files to a new directory</b></p> | <p><b>Move a set of files to a new directory</b></p> | ||||
<pre> | <pre> | ||||
@@ -59,11 +59,78 @@ | |||||
</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"> | |||||
<condition> | |||||
<not> | |||||
<available file="E/1" type="file" /> | |||||
</not> | |||||
</condition> | |||||
</fail> | |||||
<fail message="A remains"> | |||||
<condition> | |||||
<available file="A" type="dir" /> | |||||
</condition> | |||||
</fail> | |||||
</target> | |||||
<target name="testCompleteDirectoryMoveFileToDir"> | |||||
<mkdir dir="A"/> | |||||
<touch file="A/1"/> | |||||
<move file="A" todir="E" /> | |||||
<fail message="E/A/1 not available"> | |||||
<condition> | |||||
<not> | |||||
<available file="E/A/1" type="file" /> | |||||
</not> | |||||
</condition> | |||||
</fail> | |||||
<fail message="A remains"> | |||||
<condition> | |||||
<available file="A" type="dir" /> | |||||
</condition> | |||||
</fail> | |||||
</target> | |||||
<target name="testCompleteDirectoryMoveFileToExistingFile"> | |||||
<mkdir dir="A"/> | |||||
<touch file="A/1"/> | |||||
<touch file="B"/> | |||||
<move file="A" tofile="B" /> | |||||
</target> | |||||
<target name="testCompleteDirectoryMoveFileToExistingDir"> | |||||
<mkdir dir="A"/> | |||||
<touch file="A/1"/> | |||||
<mkdir dir="E"/> | |||||
<move file="A" tofile="E" /> | |||||
</target> | |||||
<target name="testCompleteDirectoryMoveFileToDirWithExistingFile"> | |||||
<mkdir dir="A"/> | |||||
<touch file="A/1"/> | |||||
<mkdir dir="E"/> | |||||
<touch file="E/A"/> | |||||
<move file="A" todir="E" /> | |||||
</target> | |||||
<target name="testCompleteDirectoryMoveFileToDirWithExistingDir"> | |||||
<mkdir dir="A"/> | |||||
<touch file="A/1"/> | |||||
<mkdir dir="E"/> | |||||
<mkdir dir="E/A"/> | |||||
<move file="A" todir="E" /> | |||||
</target> | |||||
<target name="cleanup"> | <target name="cleanup"> | ||||
<delete file="move.filterset.tmp"/> | <delete file="move.filterset.tmp"/> | ||||
<delete file="move.filterchain.tmp"/> | <delete file="move.filterchain.tmp"/> | ||||
<delete dir="A"/> | |||||
<delete dir="E"/> | |||||
<delete dir="A" /> | |||||
<delete file="B" /> | |||||
<delete dir="E" /> | |||||
</target> | </target> | ||||
</project> | </project> |
@@ -61,6 +61,58 @@ public class Move extends Copy { | |||||
setOverwrite(true); | setOverwrite(true); | ||||
} | } | ||||
/** | |||||
* Performs the move operation. | |||||
*/ | |||||
public void execute() throws BuildException { | |||||
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) { | |||||
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; | |||||
} | |||||
} | |||||
} else { | |||||
super.execute(); | |||||
} | |||||
} | |||||
//************************************************************************ | //************************************************************************ | ||||
// protected and private methods | // protected and private methods | ||||
//************************************************************************ | //************************************************************************ | ||||
@@ -325,17 +377,19 @@ public class Move extends Copy { | |||||
} else { | } else { | ||||
if (!filtering) { | if (!filtering) { | ||||
// ensure that parent dir of dest file exists! | // ensure that parent dir of dest file exists! | ||||
// not using getParentFile method to stay 1.1 compatibility | |||||
String parentPath = destFile.getParent(); | |||||
if (parentPath != null) { | |||||
File parent = new File(parentPath); | |||||
if (!parent.exists()) { | |||||
parent.mkdirs(); | |||||
} | |||||
File parent = destFile.getParentFile(); | |||||
if (parent != null && !parent.exists()) { | |||||
parent.mkdirs(); | |||||
} | } | ||||
if (destFile.exists() && destFile.isFile()) { | |||||
if (!destFile.delete()) { | |||||
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 " | throw new BuildException("Unable to remove existing " | ||||
+ "file " + destFile); | + "file " + destFile); | ||||
} | } | ||||
@@ -88,4 +88,33 @@ public class MoveTest extends BuildFileTest { | |||||
assertTrue(!getProject().resolveFile("A/1").exists()); | assertTrue(!getProject().resolveFile("A/1").exists()); | ||||
assertTrue(!getProject().resolveFile("A").exists()); | assertTrue(!getProject().resolveFile("A").exists()); | ||||
} | } | ||||
public void testCompleteDirectoryMoveFileToFile() { | |||||
executeTarget("testCompleteDirectoryMoveFileToFile"); | |||||
} | |||||
public void testCompleteDirectoryMoveFileToDir() { | |||||
executeTarget("testCompleteDirectoryMoveFileToDir"); | |||||
} | |||||
public void testCompleteDirectoryMoveFileToExistingFile() { | |||||
expectBuildExceptionContaining("testCompleteDirectoryMoveFileToExistingFile", | |||||
"", "Cannot replace file"); | |||||
} | |||||
public void testCompleteDirectoryMoveFileToExistingDir() { | |||||
expectBuildExceptionContaining("testCompleteDirectoryMoveFileToExistingDir", | |||||
"", "Cannot replace directory"); | |||||
} | |||||
public void testCompleteDirectoryMoveFileToDirWithExistingFile() { | |||||
expectBuildExceptionContaining("testCompleteDirectoryMoveFileToDirWithExistingFile", | |||||
"", "Cannot replace file"); | |||||
} | |||||
public void testCompleteDirectoryMoveFileToDirWithExistingDir() { | |||||
expectBuildExceptionContaining("testCompleteDirectoryMoveFileToDirWithExistingDir", | |||||
"", "Cannot replace directory"); | |||||
} | |||||
} | } |