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]

Reply via email to