diff --git a/docs/manual/CoreTasks/zip.html b/docs/manual/CoreTasks/zip.html
index d3f95a586..cba2c0aa4 100644
--- a/docs/manual/CoreTasks/zip.html
+++ b/docs/manual/CoreTasks/zip.html
@@ -199,16 +199,12 @@ to a value other than its default, "add"
.
The zip task supports any number of nested <fileset>
elements to specify
-the files to be included in the archive.
The zip task supports any number of nested <zipfileset>
elements to specify
-the files to be included in the archive.
Resource +Collections are used to select groups of files to archive.
+Prior to Ant 1.7 only <fileset>
and
+<zipfileset>
have been supported as nested elements.
A <zipgroupfileset>
allows for multiple zip files to be
@@ -273,6 +269,17 @@ The code
zips all files in the htdocs/manual
directory into the docs/user-guide
directory in the archive and includes all the files in any file that maches examples*.zip
, such as all files within examples1.zip
or examples_for_brian.zip
.
+
+
+<zip dest="release.zip"> + <tarfileset src="release.tar"/> +</zip> ++ +
Re-packages a TAR archive as a ZIP archive. If Unix file +permissions have been stored as part of the TAR file, they will be +retained in the resulting ZIP archive.
+Copyright © 2000-2005 The Apache Software Foundation. All rights Reserved.
diff --git a/src/etc/testcases/taskdefs/zip.xml b/src/etc/testcases/taskdefs/zip.xml index da488d46a..12ab7a9ad 100644 --- a/src/etc/testcases/taskdefs/zip.xml +++ b/src/etc/testcases/taskdefs/zip.xml @@ -167,6 +167,25 @@ update="true"/> +If we are going to recreate the archive instead of updating
+ * it, all resources should be considered as new, if a single one
+ * is. Because of this, subclasses overriding this method must
+ * call super.getResourcesToAdd
and indicate with the
+ * third arg if they already know that the archive is
+ * out-of-date.
This method first delegates to getNonFileSetResourceToAdd + * and then invokes the FileSet-arg version. All this to keep + * backwards compatibility for subclasses that don't know how to + * deal with non-FileSet ResourceCollections.
+ * + * @param rcs The resource collections to grab resources from + * @param zipFile intended archive file (may or may not exist) + * @param needsUpdate whether we already know that the archive is + * out-of-date. Subclasses overriding this method are supposed to + * set this value correctly in their call to + *super.getResourcesToAdd
.
+ * @return an array of resources to add for each fileset passed in as well
+ * as a flag that indicates whether the archive is uptodate.
+ *
+ * @exception BuildException if it likes
+ * @since Ant 1.7
+ */
+ protected ArchiveState getResourcesToAdd(ResourceCollection[] rcs,
+ File zipFile,
+ boolean needsUpdate)
+ throws BuildException {
+ ArrayList filesets = new ArrayList();
+ ArrayList rest = new ArrayList();
+ for (int i = 0; i < rcs.length; i++) {
+ if (rcs[i] instanceof FileSet) {
+ filesets.add(rcs[i]);
+ } else {
+ rest.add(rcs[i]);
+ }
+ }
+ ResourceCollection[] rc = (ResourceCollection[])
+ rest.toArray(new ResourceCollection[rest.size()]);
+ ArchiveState as = getNonFileSetResourcesToAdd(rc, zipFile,
+ needsUpdate);
+
+ FileSet[] fs = (FileSet[]) filesets.toArray(new FileSet[filesets
+ .size()]);
+ ArchiveState as2 = getResourcesToAdd(fs, zipFile, as.isOutOfDate());
+ if (!as.isOutOfDate() && as2.isOutOfDate()) {
+ /*
+ * Bad luck.
+ *
+ * There are resources in the filesets that make the
+ * archive out of date, but not in the non-fileset
+ * resources. We need to rescan the non-FileSets to grab
+ * all of them now.
+ */
+ as = getNonFileSetResourcesToAdd(rc, zipFile, true);
+ }
+
+ Resource[][] toAdd = new Resource[rcs.length][];
+ int fsIndex = 0;
+ int restIndex = 0;
+ for (int i = 0; i < rcs.length; i++) {
+ if (rcs[i] instanceof FileSet) {
+ toAdd[i] = as2.getResourcesToAdd()[fsIndex++];
+ } else {
+ toAdd[i] = as.getResourcesToAdd()[restIndex++];
+ }
+ }
+ return new ArchiveState(as2.isOutOfDate(), toAdd);
+ }
+
/**
* Collect the resources that are newer than the corresponding
* entries (or missing) in the original archive.
@@ -981,6 +1152,99 @@ public class Zip extends MatchingTask {
return new ArchiveState(needsUpdate, newerResources);
}
+ /**
+ * Collect the resources that are newer than the corresponding
+ * entries (or missing) in the original archive.
+ *
+ * If we are going to recreate the archive instead of updating
+ * it, all resources should be considered as new, if a single one
+ * is. Because of this, subclasses overriding this method must
+ * call super.getResourcesToAdd
and indicate with the
+ * third arg if they already know that the archive is
+ * out-of-date.
super.getResourcesToAdd
.
+ * @return an array of resources to add for each fileset passed in as well
+ * as a flag that indicates whether the archive is uptodate.
+ *
+ * @exception BuildException if it likes
+ */
+ protected ArchiveState getNonFileSetResourcesToAdd(ResourceCollection[] rcs,
+ File zipFile,
+ boolean needsUpdate)
+ throws BuildException {
+ /*
+ * Backwards compatibility forces us to repeat the logic of
+ * getResourcesToAdd(FileSet[], ...) here once again.
+ */
+
+ Resource[][] initialResources = grabNonFileSetResources(rcs);
+ if (isEmpty(initialResources)) {
+ // no emptyBehavior handling since the FileSet version
+ // will take care of it.
+ return new ArchiveState(needsUpdate, initialResources);
+ }
+
+ // initialResources is not empty
+
+ if (!zipFile.exists()) {
+ return new ArchiveState(true, initialResources);
+ }
+
+ if (needsUpdate && !doUpdate) {
+ // we are recreating the archive, need all resources
+ return new ArchiveState(true, initialResources);
+ }
+
+ Resource[][] newerResources = new Resource[rcs.length][];
+
+ for (int i = 0; i < rcs.length; i++) {
+ if (initialResources[i].length == 0) {
+ newerResources[i] = new Resource[] {};
+ continue;
+ }
+
+ for (int j = 0; j < initialResources[i].length; j++) {
+ if (initialResources[i][j] instanceof FileResource
+ && zipFile.equals(((FileResource)
+ initialResources[i][j]).getFile())) {
+ throw new BuildException("A zip file cannot include "
+ + "itself", getLocation());
+ }
+ }
+
+ Resource[] rs = initialResources[i];
+ if (doFilesonly) {
+ rs = selectFileResources(rs);
+ }
+
+ newerResources[i] =
+ ResourceUtils.selectOutOfDateSources(this,
+ rs,
+ new IdentityMapper(),
+ getZipScanner());
+ needsUpdate = needsUpdate || (newerResources[i].length > 0);
+
+ if (needsUpdate && !doUpdate) {
+ // we will return initialResources anyway, no reason
+ // to scan further.
+ break;
+ }
+ }
+
+ if (needsUpdate && !doUpdate) {
+ // we are recreating the archive, need all resources
+ return new ArchiveState(true, initialResources);
+ }
+
+ return new ArchiveState(needsUpdate, newerResources);
+ }
+
/**
* Fetch all included and not excluded resources from the sets.
*
@@ -1023,6 +1287,35 @@ public class Zip extends MatchingTask {
return result;
}
+ /**
+ * Fetch all included and not excluded resources from the collections.
+ *
+ * Included directories will precede included files.
+ * @param rcs an array of resource collections + * @return the resources included + * @since Ant 1.7 + */ + protected Resource[][] grabNonFileSetResources(ResourceCollection[] rcs) { + Resource[][] result = new Resource[rcs.length][]; + for (int i = 0; i < rcs.length; i++) { + Iterator iter = rcs[i].iterator(); + ArrayList rs = new ArrayList(); + int lastDir = 0; + while (iter.hasNext()) { + Resource r = (Resource) iter.next(); + if (r.isExists()) { + if (r.isDirectory()) { + rs.add(lastDir++, r); + } else { + rs.add(r); + } + } + } + result[i] = (Resource[]) rs.toArray(new Resource[rs.size()]); + } + return result; + } + /** * Add a directory to the zip stream. * @param dir the directort to add to the archive @@ -1273,7 +1566,7 @@ public class Zip extends MatchingTask { Enumeration e = filesetsFromGroupfilesets.elements(); while (e.hasMoreElements()) { ZipFileSet zf = (ZipFileSet) e.nextElement(); - filesets.removeElement(zf); + resources.removeElement(zf); } filesetsFromGroupfilesets.removeAllElements(); } @@ -1287,7 +1580,7 @@ public class Zip extends MatchingTask { * @see #cleanUp */ public void reset() { - filesets.removeAllElements(); + resources.removeAllElements(); zipFile = null; baseDir = null; groupfilesets.removeAllElements(); diff --git a/src/testcases/org/apache/tools/ant/taskdefs/ZipTest.java b/src/testcases/org/apache/tools/ant/taskdefs/ZipTest.java index cf1923d5a..b362c9a16 100644 --- a/src/testcases/org/apache/tools/ant/taskdefs/ZipTest.java +++ b/src/testcases/org/apache/tools/ant/taskdefs/ZipTest.java @@ -16,7 +16,9 @@ */ package org.apache.tools.ant.taskdefs; + import org.apache.tools.ant.BuildFileTest; +import org.apache.tools.zip.UnixStat; import java.io.File; import java.io.IOException; @@ -165,4 +167,27 @@ public class ZipTest extends BuildFileTest { } } } + + public void testFileResource() { + executeTarget("testFileResource"); + } + + public void testNonFileResource() { + executeTarget("testNonFileResource"); + } + + public void testTarFileSet() throws IOException { + executeTarget("testTarFileSet"); + org.apache.tools.zip.ZipFile zf = null; + try { + zf = new org.apache.tools.zip.ZipFile(getProject() + .resolveFile("test3.zip")); + org.apache.tools.zip.ZipEntry ze = zf.getEntry("asf-logo.gif"); + assertEquals(UnixStat.FILE_FLAG | 0446, ze.getUnixMode()); + } finally { + if (zf != null) { + zf.close(); + } + } + } }