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"); | |||||
| } | |||||
| } | } | ||||