add a flatten to unzip. I actually only patched in the mapper nested element support; with that the flatten attribute can only introduce inconsistency (what if you spec a mapper and flatten=true). And the patch was modified to keep the attributes private, with a getMapper() operation for subclasses (like untar) to get when needed. Did a bit of cleanup -especially of the unzip tests- while at it. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@276981 13f79535-47bb-0310-9956-ffa450edef68master
@@ -15,9 +15,12 @@ carried from the archive file.</p> | |||
<p><a href="../CoreTypes/patternset.html">PatternSet</a>s are used to select files to extract | |||
<I>from</I> the archive. If no patternset is used, all files are extracted. | |||
</p> | |||
<p><a href="../CoreTypes/fileset.html">FileSet</a>s may be used used to select archived files | |||
<p><a href="../CoreTypes/fileset.html">FileSet</a>s may be used to select archived files | |||
to perform unarchival upon. | |||
</p> | |||
<p>You can define filename transformations by using a nested <a href="../CoreTypes/mapper.html">mapper</a> element. The default mapper is the | |||
<a href="../CoreTypes/mapper.html#identity-mapper">identity mapper</a>. | |||
</p> | |||
<p>File permissions will not be restored on extracted files.</p> | |||
<p>The untar task recognizes the long pathname entries used by GNU tar.<p> | |||
<h3>Parameters</h3> | |||
@@ -102,6 +105,16 @@ to perform unarchival upon. | |||
</unzip> | |||
</pre></p> | |||
</blockquote> | |||
<blockquote> | |||
<p><pre> | |||
<unzip src="apache-ant-bin.zip" dest="${tools.home}"> | |||
<patternset> | |||
<include name="apache-ant/lib/ant.jar"/> | |||
</patternset> | |||
<mapper type="flatten"/> | |||
</unzip> | |||
</pre></p> | |||
</blockquote> | |||
<hr> | |||
<p align="center">Copyright © 2000-2004 The Apache Software Foundation. All rights | |||
Reserved.</p> | |||
@@ -93,4 +93,33 @@ | |||
<unzip src="unziptest.zip" dest="unziptestout" encoding="UnicodeBig"/> | |||
</target> | |||
<!-- Bugzilla Report 21996 --> | |||
<target name="testFlattenMapper" depends="prepareTestZip"> | |||
<unzip dest="unziptestout" src="unziptest.zip"> | |||
<patternset> | |||
<include name="1/**"/> | |||
</patternset> | |||
<mapper type="flatten"/> | |||
</unzip> | |||
</target> | |||
<!-- Bugzilla Report 21996 --> | |||
<target name="testGlobMapper" depends="prepareTestZip"> | |||
<unzip dest="unziptestout" src="unziptest.zip"> | |||
<patternset> | |||
<include name="1/**"/> | |||
</patternset> | |||
<mapper type="glob" from="*" to="*.txt"/> | |||
</unzip> | |||
</target> | |||
<target name="testTwoMappers" depends="prepareTestZip"> | |||
<unzip dest="unziptestout" src="unziptest.zip"> | |||
<patternset> | |||
<include name="1/**"/> | |||
</patternset> | |||
<mapper type="glob" from="*" to="*.txt"/> | |||
<mapper type="flatten"/> | |||
</unzip> | |||
</target> | |||
</project> |
@@ -30,9 +30,13 @@ import org.apache.tools.ant.DirectoryScanner; | |||
import org.apache.tools.ant.Project; | |||
import org.apache.tools.ant.Task; | |||
import org.apache.tools.ant.types.FileSet; | |||
import org.apache.tools.ant.types.Mapper; | |||
import org.apache.tools.ant.types.PatternSet; | |||
import org.apache.tools.ant.types.selectors.SelectorUtils; | |||
import org.apache.tools.ant.util.FileNameMapper; | |||
import org.apache.tools.ant.util.FileUtils; | |||
import org.apache.tools.ant.util.FlatFileNameMapper; | |||
import org.apache.tools.ant.util.IdentityMapper; | |||
import org.apache.tools.zip.ZipEntry; | |||
import org.apache.tools.zip.ZipFile; | |||
@@ -50,12 +54,14 @@ public class Expand extends Task { | |||
private File dest; //req | |||
private File source; // req | |||
private boolean overwrite = true; | |||
private Mapper mapperElement = null; | |||
private Vector patternsets = new Vector(); | |||
private Vector filesets = new Vector(); | |||
private static final String NATIVE_ENCODING = "native-encoding"; | |||
private String encoding = "UTF8"; | |||
public static final String ERROR_MULTIPLE_MAPPERS = "Cannot define more than one mapper"; | |||
/** | |||
* Do the work. | |||
@@ -106,12 +112,17 @@ public class Expand extends Task { | |||
} | |||
} | |||
/* | |||
/** | |||
* This method is to be overridden by extending unarchival tasks. | |||
* | |||
* @param fileUtils | |||
* @param srcF | |||
* @param dir | |||
*/ | |||
protected void expandFile(FileUtils fileUtils, File srcF, File dir) { | |||
log("Expanding: " + srcF + " into " + dir, Project.MSG_INFO); | |||
ZipFile zf = null; | |||
FileNameMapper mapper = getMapper(); | |||
try { | |||
zf = new ZipFile(srcF, encoding); | |||
Enumeration e = zf.getEntries(); | |||
@@ -119,7 +130,7 @@ public class Expand extends Task { | |||
ZipEntry ze = (ZipEntry) e.nextElement(); | |||
extractFile(fileUtils, srcF, dir, zf.getInputStream(ze), | |||
ze.getName(), new Date(ze.getTime()), | |||
ze.isDirectory()); | |||
ze.isDirectory(), mapper); | |||
} | |||
log("expand complete", Project.MSG_VERBOSE); | |||
@@ -127,20 +138,40 @@ public class Expand extends Task { | |||
throw new BuildException("Error while expanding " + srcF.getPath(), | |||
ioe); | |||
} finally { | |||
if (zf != null) { | |||
try { | |||
zf.close(); | |||
} catch (IOException e) { | |||
//ignore | |||
} | |||
} | |||
ZipFile.closeQuietly(zf); | |||
} | |||
} | |||
/** | |||
* get a mapper for a file | |||
* @return | |||
*/ | |||
protected FileNameMapper getMapper() { | |||
FileNameMapper mapper = null; | |||
if (mapperElement != null) { | |||
mapper = mapperElement.getImplementation(); | |||
} else { | |||
mapper = new IdentityMapper(); | |||
} | |||
return mapper; | |||
} | |||
/** | |||
* extract a file to a directory | |||
* @param fileUtils | |||
* @param srcF | |||
* @param dir | |||
* @param compressedInputStream | |||
* @param entryName | |||
* @param entryDate | |||
* @param isDirectory | |||
* @param mapper | |||
* @throws IOException | |||
*/ | |||
protected void extractFile(FileUtils fileUtils, File srcF, File dir, | |||
InputStream compressedInputStream, | |||
String entryName, | |||
Date entryDate, boolean isDirectory) | |||
String entryName, Date entryDate, | |||
boolean isDirectory, FileNameMapper mapper) | |||
throws IOException { | |||
if (patternsets != null && patternsets.size() > 0) { | |||
@@ -194,7 +225,11 @@ public class Expand extends Task { | |||
return; | |||
} | |||
} | |||
File f = fileUtils.resolveFile(dir, entryName); | |||
String[] mappedNames = mapper.mapFileName(entryName); | |||
if (mappedNames == null || mappedNames.length == 0) { | |||
mappedNames = new String[] { entryName }; | |||
} | |||
File f = fileUtils.resolveFile(dir, mappedNames[0]); | |||
try { | |||
if (!overwrite && f.exists() | |||
&& f.lastModified() >= entryDate.getTime()) { | |||
@@ -286,6 +321,21 @@ public class Expand extends Task { | |||
filesets.addElement(set); | |||
} | |||
/** | |||
* Defines the mapper to map source entries to destination files. | |||
* @return a mapper to be configured | |||
* @exception BuildException if more than one mapper is defined | |||
* @since Ant1.7 | |||
*/ | |||
public Mapper createMapper() throws BuildException { | |||
if (mapperElement != null) { | |||
throw new BuildException(ERROR_MULTIPLE_MAPPERS, | |||
getLocation()); | |||
} | |||
mapperElement = new Mapper(getProject()); | |||
return mapperElement; | |||
} | |||
/** | |||
* Sets the encoding to assume for file names and comments. | |||
* | |||
@@ -26,7 +26,10 @@ import java.util.zip.GZIPInputStream; | |||
import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.Project; | |||
import org.apache.tools.ant.types.EnumeratedAttribute; | |||
import org.apache.tools.ant.util.FileNameMapper; | |||
import org.apache.tools.ant.util.FileUtils; | |||
import org.apache.tools.ant.util.FlatFileNameMapper; | |||
import org.apache.tools.ant.util.IdentityMapper; | |||
import org.apache.tools.bzip2.CBZip2InputStream; | |||
import org.apache.tools.tar.TarEntry; | |||
import org.apache.tools.tar.TarInputStream; | |||
@@ -92,10 +95,11 @@ public class Untar extends Expand { | |||
new BufferedInputStream( | |||
new FileInputStream(srcF)))); | |||
TarEntry te = null; | |||
FileNameMapper mapper = getMapper(); | |||
while ((te = tis.getNextEntry()) != null) { | |||
extractFile(fileUtils, srcF, dir, tis, | |||
te.getName(), te.getModTime(), te.isDirectory()); | |||
te.getName(), te.getModTime(), | |||
te.isDirectory(), mapper); | |||
} | |||
log("expand complete", Project.MSG_VERBOSE); | |||
@@ -103,13 +107,7 @@ public class Untar extends Expand { | |||
throw new BuildException("Error while expanding " + srcF.getPath(), | |||
ioe, getLocation()); | |||
} finally { | |||
if (tis != null) { | |||
try { | |||
tis.close(); | |||
} catch (IOException e) { | |||
// ignore | |||
} | |||
} | |||
FileUtils.close(tis); | |||
} | |||
} | |||
@@ -160,6 +160,21 @@ public class ZipFile { | |||
archive.close(); | |||
} | |||
/** | |||
* close a zipfile quietly; throw no io fault, do nothing | |||
* on a null parameter | |||
* @param zipfile file to close, can be null | |||
*/ | |||
public static void closeQuietly(ZipFile zipfile) { | |||
if (zipfile != null) { | |||
try { | |||
zipfile.close(); | |||
} catch (IOException e) { | |||
//ignore | |||
} | |||
} | |||
} | |||
/** | |||
* Returns all entries. | |||
* @return all entries as {@link ZipEntry} instances | |||
@@ -19,6 +19,8 @@ package org.apache.tools.ant.taskdefs; | |||
import org.apache.tools.ant.BuildFileTest; | |||
import org.apache.tools.ant.util.FileUtils; | |||
import java.io.IOException; | |||
/** | |||
*/ | |||
public class UnzipTest extends BuildFileTest { | |||
@@ -49,24 +51,28 @@ public class UnzipTest extends BuildFileTest { | |||
public void testRealTest() throws java.io.IOException { | |||
FileUtils fileUtils = FileUtils.newFileUtils(); | |||
executeTarget("realTest"); | |||
assertLogoUncorrupted(); | |||
} | |||
/** | |||
* test that the logo gif file has not been corrupted | |||
* @throws IOException | |||
*/ | |||
private void assertLogoUncorrupted() throws IOException { | |||
FileUtils fileUtils = FileUtils.newFileUtils(); | |||
assertTrue(fileUtils.contentEquals(project.resolveFile("../asf-logo.gif"), | |||
project.resolveFile("asf-logo.gif"))); | |||
} | |||
public void testTestZipTask() throws java.io.IOException { | |||
FileUtils fileUtils = FileUtils.newFileUtils(); | |||
executeTarget("testZipTask"); | |||
assertTrue(fileUtils.contentEquals(project.resolveFile("../asf-logo.gif"), | |||
project.resolveFile("asf-logo.gif"))); | |||
assertLogoUncorrupted(); | |||
} | |||
public void testTestUncompressedZipTask() throws java.io.IOException { | |||
FileUtils fileUtils = FileUtils.newFileUtils(); | |||
executeTarget("testUncompressedZipTask"); | |||
assertTrue(fileUtils.contentEquals(project.resolveFile("../asf-logo.gif"), | |||
project.resolveFile("asf-logo.gif"))); | |||
assertLogoUncorrupted(); | |||
} | |||
/* | |||
@@ -74,10 +80,8 @@ public class UnzipTest extends BuildFileTest { | |||
*/ | |||
public void testPatternSetExcludeOnly() { | |||
executeTarget("testPatternSetExcludeOnly"); | |||
assertTrue("1/foo is excluded", | |||
!getProject().resolveFile("unziptestout/1/foo").exists()); | |||
assertTrue("2/bar is not excluded", | |||
getProject().resolveFile("unziptestout/2/bar").exists()); | |||
assertFileMissing("1/foo is excluded", "unziptestout/1/foo"); | |||
assertFileExists("2/bar is not excluded", "unziptestout/2/bar"); | |||
} | |||
/* | |||
@@ -85,10 +89,8 @@ public class UnzipTest extends BuildFileTest { | |||
*/ | |||
public void testPatternSetIncludeOnly() { | |||
executeTarget("testPatternSetIncludeOnly"); | |||
assertTrue("1/foo is not included", | |||
!getProject().resolveFile("unziptestout/1/foo").exists()); | |||
assertTrue("2/bar is included", | |||
getProject().resolveFile("unziptestout/2/bar").exists()); | |||
assertFileMissing("1/foo is not included", "unziptestout/1/foo"); | |||
assertFileExists("2/bar is included", "unziptestout/2/bar"); | |||
} | |||
/* | |||
@@ -96,10 +98,8 @@ public class UnzipTest extends BuildFileTest { | |||
*/ | |||
public void testPatternSetIncludeAndExclude() { | |||
executeTarget("testPatternSetIncludeAndExclude"); | |||
assertTrue("1/foo is not included", | |||
!getProject().resolveFile("unziptestout/1/foo").exists()); | |||
assertTrue("2/bar is excluded", | |||
!getProject().resolveFile("unziptestout/2/bar").exists()); | |||
assertFileMissing("1/foo is not included", "unziptestout/1/foo"); | |||
assertFileMissing("2/bar is excluded", "unziptestout/2/bar"); | |||
} | |||
/* | |||
@@ -115,19 +115,60 @@ public class UnzipTest extends BuildFileTest { | |||
*/ | |||
public void testPatternSetSlashOnly() { | |||
executeTarget("testPatternSetSlashOnly"); | |||
assertTrue("1/foo is not included", | |||
!getProject().resolveFile("unziptestout/1/foo").exists()); | |||
assertTrue("2/bar is included", | |||
getProject().resolveFile("unziptestout/2/bar").exists()); | |||
assertFileMissing("1/foo is not included", "unziptestout/1/foo"); | |||
assertFileExists("\"2/bar is included", "unziptestout/2/bar"); | |||
} | |||
/* | |||
* PR 10504 | |||
*/ | |||
public void testEncoding() { | |||
executeTarget("encodingTest"); | |||
assertTrue("foo has been properly named", | |||
getProject().resolveFile("unziptestout/foo").exists()); | |||
assertFileExists("foo has been properly named", "unziptestout/foo"); | |||
} | |||
/* | |||
* PR 21996 | |||
*/ | |||
public void testFlattenMapper() { | |||
executeTarget("testFlattenMapper"); | |||
assertFileMissing("1/foo is not flattened", "unziptestout/1/foo"); | |||
assertFileExists("foo is flattened", "unziptestout/foo"); | |||
} | |||
/** | |||
* assert that a file exists, relative to the project | |||
* @param message message if there is no mpatch | |||
* @param filename filename to resolve against the project | |||
*/ | |||
private void assertFileExists(String message, String filename) { | |||
assertTrue(message, | |||
getProject().resolveFile(filename).exists()); | |||
} | |||
/** | |||
* assert that a file doesnt exist, relative to the project | |||
* | |||
* @param message message if there is no mpatch | |||
* @param filename filename to resolve against the project | |||
*/ | |||
private void assertFileMissing(String message, String filename) { | |||
assertTrue(message, | |||
!getProject().resolveFile(filename).exists()); | |||
} | |||
/** | |||
* PR 21996 | |||
*/ | |||
public void testGlobMapper() { | |||
executeTarget("testGlobMapper"); | |||
assertFileMissing("1/foo is not mapped", "unziptestout/1/foo"); | |||
assertFileExists("1/foo is mapped", "unziptestout/1/foo.txt"); | |||
} | |||
public void testTwoMappers() { | |||
expectBuildException("testTwoMappers",Expand.ERROR_MULTIPLE_MAPPERS); | |||
} | |||
} |