The mailling list seems not to allow attachment. So I paste the patch here. ------------------- START PATCHING ---------------------------------
Index: org/apache/tools/ant/taskdefs/Zip.java =================================================================== --- org/apache/tools/ant/taskdefs/Zip.java (revision 1) +++ org/apache/tools/ant/taskdefs/Zip.java (working copy) @@ -733,7 +733,7 @@ zOut, prefix, dirMode); } if (zf != null) { - ZipEntry ze = zf.getEntry(resources[i].getName()); + ZipEntry ze = zf.getEntry(zfs.getBasedir() + resources[i].getName()); addParentDirs(base, name, zOut, prefix, ze.getUnixMode()); } else { @@ -752,7 +752,7 @@ zipFile(f, zOut, prefix + name, fileMode); } else if (!resources[i].isDirectory()) { if (zf != null) { - ZipEntry ze = zf.getEntry(resources[i].getName()); + ZipEntry ze = zf.getEntry(zfs.getBasedir() + resources[i].getName()); if (ze != null) { boolean oldCompress = doCompress; Index: org/apache/tools/ant/types/ArchiveScanner.java =================================================================== --- org/apache/tools/ant/types/ArchiveScanner.java (revision 1) +++ org/apache/tools/ant/types/ArchiveScanner.java (working copy) @@ -45,6 +45,11 @@ */ protected File srcFile; + /** + * The basedir from which this scanner begins to scan. + */ + protected String basedir; + // CheckStyle:VisibilityModifier ON /** @@ -119,6 +124,32 @@ } /** + * Sets the basedir for scanning. + * + * @param basedir path name inside the zip file + */ + public void setBasedir(String basedir) { + if ((basedir != null) && (basedir.length() > 0)) { + + // Make sure the basedir: + // 1. BE separated by slash '/', + // 2. NOT starts with slash '/' + // 3. ALWAYS ends with slash '/' + basedir = basedir.replace('\\', '/'); + + if (basedir.startsWith("/")) { + basedir = basedir.substring(1); + } + + if (!basedir.endsWith("/")) { + basedir += "/"; + } + + this.basedir = basedir; + } + } + + /** * Sets encoding of file names. * @param encoding the encoding format * @since Ant 1.6 @@ -331,5 +362,23 @@ protected static final String trimSeparator(String s) { return s.endsWith("/") ? s.substring(0, s.length() - 1) : s; } + + /** + * if the basedir was specified, and the entry name (path) is under the basedir, + * just save the relative path to the basedir. + * Again, make sure the entry name is separated by slash '/'. + */ + protected final String trimBasedir(String name) { + name = name.replace('\\', '/'); + if (basedir != null) { + if (name.startsWith(basedir)) { + name = name.substring(basedir.length()); + } else { + name = null; + } + } + + return name; + } } Index: org/apache/tools/ant/types/ZipScanner.java =================================================================== --- org/apache/tools/ant/types/ZipScanner.java (revision 1) +++ org/apache/tools/ant/types/ZipScanner.java (working copy) @@ -77,7 +77,15 @@ while (e.hasMoreElements()) { entry = (ZipEntry) e.nextElement(); Resource r = new ZipResource(srcFile, encoding, entry); - String name = entry.getName(); + String name = trimBasedir(entry.getName()); + + if (name == null || name.length() == 0) { + continue; + } + + // set basedir-trimmed name as resource name + r.setName(name); + if (entry.isDirectory()) { name = trimSeparator(name); dirEntries.put(name, r); Index: org/apache/tools/ant/types/ArchiveFileSet.java =================================================================== --- org/apache/tools/ant/types/ArchiveFileSet.java (revision 1) +++ org/apache/tools/ant/types/ArchiveFileSet.java (working copy) @@ -56,6 +56,7 @@ UnixStat.FILE_FLAG | UnixStat.DEFAULT_FILE_PERM; private Resource src = null; + private String basedir = null; private String prefix = ""; private String fullpath = ""; private boolean hasDir = false; @@ -87,6 +88,7 @@ src = fileset.src; prefix = fileset.prefix; fullpath = fileset.fullpath; + basedir = fileset.basedir; hasDir = fileset.hasDir; fileMode = fileset.fileMode; dirMode = fileset.dirMode; @@ -223,6 +225,42 @@ } /** + * Sets the basedir inside the source archive file. + * + * @param basedir the basedir + */ + public void setBasedir(String basedir) { + if ((basedir != null) && (basedir.length() > 0)) { + + // Make sure the basedir: + // 1. BE separated by slash '/', + // 2. NOT starts with slash '/' + // 3. ALWAYS ends with slash '/' + basedir = basedir.replace('\\', '/'); + + if (basedir.startsWith("/")) { + basedir = basedir.substring(1); + } + + if (!basedir.endsWith("/")) { + basedir += "/"; + } + + this.basedir = basedir; + } + } + + /** + * Gets the basedir inside the source archive file. + * + * @return the basedir + */ + public String getBasedir() { + return (basedir == null) ? "" + : basedir; + } + + /** * Creates a scanner for this type of archive. * @return the scanner. */ @@ -250,6 +288,7 @@ } ArchiveScanner as = newArchiveScanner(); as.setSrc(src); + as.setBasedir(getBasedir()); super.setDir(p.getBaseDir()); setupDirectoryScanner(as, p); as.init(); ------------------- END OF PATCH --------------------------------- Forwarded by Michael Zhou <[EMAIL PROTECTED]> ----------------------- Original Message ----------------------- From: Michael Zhou <[EMAIL PROTECTED]> To: dev@ant.apache.org Date: Wed, 08 Aug 2007 16:38:31 +0800 Subject: Contribute: use zipfileset to extract sub-path of zips ---- I used to build a jar file (or any zip-format file: war, ear, etc.), which contents are extracted from other zip files. For instance, zip file src.zip contains: +---main | \---org | \---apache | Test.java | \---test I just want the subtree under "main" (not include main directory) to be packed into my jar file: +---org \---apache Test.java So I wrote a build.xml to do this: <project default="src-jar"> <target name="src-jar"> <jar destfile="my-src.jar"> <zipfileset src="src.zip" includes="main/"/> </jar> </target> </project> But the result is not as expected: +---main // I don't want this directory here \---org \---apache Test.java In order to take off the "main" directory, I modified some Ant classes. Attachment is the patch file from Ant 1.7.0 source. Usage: <project default="src-jar"> <target name="src-jar"> <jar destfile="my-src.jar"> <!-- basedir instead of includes --> <zipfileset src="src.zip" basedir="main/"/> </jar> </target> </project> This is not the best solution I think. Because it doesn't support tasks other than "zip", "jar", "war". For example, the following build script won't work: <project default="copy-src"> <target name="copy-src"> <copy destfile="srcdir"> <zipfileset src="src.zip" basedir="main/"/> </copy> </target> </project> I suggest to improve class org.apache.tools.zip.ZipFile to support new zip file format like "src.zip!/main". By this way, any tasks use zipfileset do not need to be changed. For example, <project default="copy-src"> <target name="copy-src"> <copy destfile="srcdir"> <zipfileset src="src.zip!/main" includes="**/*.java"/> </copy> </target> </project> Michael Zhou <[EMAIL PROTECTED]> --------------------- Original Message Ends -------------------- -- Michael Zhou <[EMAIL PROTECTED]> --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]