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 | |||
| schemas (files or urls) can be named in the <schema> element. | |||
| 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 | |||
| ===================================================== | |||
| @@ -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> | |||
| <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> | |||
| <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> | |||
| <table border="1" cellpadding="2" cellspacing="0"> | |||
| <tr> | |||
| @@ -25,7 +29,7 @@ to move to the <var>todir</var> directory.</p> | |||
| </tr> | |||
| <tr> | |||
| <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 | |||
| at least one nested fileset element</td> | |||
| </tr> | |||
| @@ -78,7 +82,7 @@ to move to the <var>todir</var> directory.</p> | |||
| </tr> | |||
| <tr> | |||
| <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 | |||
| filesets points to a directory that doesn't exist or an error occurs | |||
| while moving. | |||
| @@ -154,6 +158,10 @@ followed by <filterset> elements. | |||
| <move todir="new/dir/to/move/to"> | |||
| <fileset dir="src/dir"/> | |||
| </move> | |||
| </pre> | |||
| <i>or, since Ant 1.6.3:</i> | |||
| <pre> | |||
| <move file="src/dir" tofile="new/dir/to/move/to" /> | |||
| </pre> | |||
| <p><b>Move a set of files to a new directory</b></p> | |||
| <pre> | |||
| @@ -59,11 +59,78 @@ | |||
| </move> | |||
| </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"> | |||
| <delete file="move.filterset.tmp"/> | |||
| <delete file="move.filterchain.tmp"/> | |||
| <delete dir="A"/> | |||
| <delete dir="E"/> | |||
| <delete dir="A" /> | |||
| <delete file="B" /> | |||
| <delete dir="E" /> | |||
| </target> | |||
| </project> | |||
| @@ -61,6 +61,58 @@ public class Move extends Copy { | |||
| 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 | |||
| //************************************************************************ | |||
| @@ -325,17 +377,19 @@ public class Move extends Copy { | |||
| } else { | |||
| if (!filtering) { | |||
| // 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 " | |||
| + "file " + destFile); | |||
| } | |||
| @@ -88,4 +88,33 @@ public class MoveTest extends BuildFileTest { | |||
| assertTrue(!getProject().resolveFile("A/1").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"); | |||
| } | |||
| } | |||