ant-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bugzi...@apache.org
Subject DO NOT REPLY [Bug 43067] New: - Enhanced zipfileset to extract sub-path of zips
Date Thu, 09 Aug 2007 01:55:23 GMT
DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG·
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://issues.apache.org/bugzilla/show_bug.cgi?id=43067>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND·
INSERTED IN THE BUG DATABASE.

http://issues.apache.org/bugzilla/show_bug.cgi?id=43067

           Summary: Enhanced zipfileset to extract sub-path of zips
           Product: Ant
           Version: 1.7.0
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: enhancement
          Priority: P2
         Component: Core tasks
        AssignedTo: dev@ant.apache.org
        ReportedBy: zhouyuehong@21cn.com


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>

Patch file to ant 1.7.0 lists below.

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();

-- 
Configure bugmail: http://issues.apache.org/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug, or are watching the assignee.

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@ant.apache.org
For additional commands, e-mail: dev-help@ant.apache.org


Mime
View raw message