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