You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@ant.apache.org by Cyril Sagan <cy...@unx.sas.com> on 2007/06/14 02:05:07 UTC

replace an entry in a zip file?

GOAL:  To replace one entry in a zip file with an updated file.

I cannot find an elegant way to do this, short of <unzip>'ing the
archive, replacing the file of interest and then re-<zip>.  It seems
there should be a better way.  Can anyone help?

Thanks.

--Cyril


FWIW, It looks like the Ant 1.6.5 source code *tried* to support this.
Note that the comment describes a the setting "overwrite" for the
duplicate attribute of <zip> task which would provide exactly what I
want, the bad news is that it doesn't seem to be implemented.  :-(

I've included the comment, and the duplicate logic below.

>From src/main/org/apache/tools/ant/taskdefs/Zip.java:
...       

    /**
     * Sets behavior for when a duplicate file is about to be added -
     * one of <code>keep</code>, <code>skip</code> or <code>overwrite</code>.
     * Possible values are: <code>keep</code> (keep both
     * of the files); <code>skip</code> (keep the first version
     * of the file found); <code>overwrite</code> overwrite the file
     * with the new file
     * Default for zip tasks is <code>keep</code>
     */
    public void setDuplicate(Duplicate df) {
        duplicate = df.getValue();
    }

...
    /**
     * Adds a new entry to the archive, takes care of duplicates as well.
     *
     * @param in the stream to read data for the entry from.
     * @param zOut the stream to write to.
     * @param vPath the name this entry shall have in the archive.
     * @param lastModified last modification time for the entry.
     * @param fromArchive the original archive we are copying this
     * entry from, will be null if we are not copying from an archive.
     * @param mode the Unix permissions to set.
     *
     * @since Ant 1.5.2
     */
    protected void zipFile(InputStream in, ZipOutputStream zOut, String vPath,
                           long lastModified, File fromArchive, int mode)
        throws IOException {
        if (entries.contains(vPath)) {

            if (duplicate.equals("preserve")) {
                log(vPath + " already added, skipping", Project.MSG_INFO);
                return;
            } else if (duplicate.equals("fail")) {
                throw new BuildException("Duplicate file " + vPath
                                         + " was found and the duplicate "
                                         + "attribute is 'fail'.");
            } else {
                // duplicate equal to add, so we continue
                log("duplicate file " + vPath
                    + " found, adding.", Project.MSG_VERBOSE);
            }
        } else {
            log("adding entry " + vPath, Project.MSG_VERBOSE);
        }


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


Re: replace an entry in a zip file?

Posted by Peter Reilly <pe...@gmail.com>.
Whats wrong is that he was using <jar> instead of <zip>.
<jar> will create a manifest entry in the jarfile. The
timestamp of this manifest entry will the time
time that the <jar> task was run - (if there
are updates to be done). One cannot mix
<jar> and <zip updating manifest file>.
Peter


On 6/14/07, RADEMAKERS Tanguy <Ta...@swift.com> wrote:
> that's weird, i'm using 1.6.5 as well.
>
> I think we have a misunderstanding.
>
> Here's what i did:
>
> 1) make three files a.txt, b.txt, c.txt, each with some text
>
> 2) create the following build.xml:
>
> <?xml version="1.0" encoding="UTF-8"?>
> <project name="bollo" default="testzip" basedir=".">
>     <target name="testzip">
>         <zip destfile="txtfiles.zip" update="true">
>             <fileset dir="." includes="*.txt"/>
>         </zip>
>     </target>
> </project>
>
> 3) run that to get the first zip file: txtfiles.zip, containing the
> three txt files listed above.
>
> 4) move b.txt and c.txt to b.bak and c.bak (so the zip task no longer
> sees them) and update a.txt (add a string "updated")
>
> 5) re-run the build, and the updated zip archive txtfiles.zip now
> contains the original versions of b.txt and c.txt, but the updated
> version of a.txt.
>
> In my book, that's equivalent to "replace one entry in a zip file with
> an updated file", no?
>
> /t
>
> >-----Original Message-----
> >From: Cyril Sagan [mailto:Cyril.Sagan@sas.com]
> >Sent: Thursday, June 14, 2007 6:12 PM
> >To: Ant Users List
> >Subject: RE: replace an entry in a zip file?
> >
> >Thanks for your reponse.  However, this does not work for me
> >in Ant 1.6.5.
> >Note that my goal is to *replace* a file that's already in the zip.
> >
> >Seems like the best solution would be for the duplicate
> >attribute to support a "replace" option.
> >
> >FWIW, I'm doing this to control my jar manifest.  I can't use
> ><jar> because Ant merges with its default manifest.  I'm
> >having a hard time employing this advice from the Ant doc:
> >
> >http://ant.apache.org/manual/CoreTasks/manifest.html
> >
> >    If you find that Ant generates manifests incompatible with your
> >    runtime, take a manifest it has built, fix it up however you need
> >    and switch to using the <zip>  task to create the JAR, feeding in
> >    the hand-crafted manifest.
> >
> >Here's my build.xml:
> >
> ><?xml version="1.0"?>
> ><project name="manifest_test" default="go">
> >
> >    <target name="go">
> >        <!-- build trivial sample jar -->
> >        <mkdir dir="work" />
> >        <touch file="work/a" />
> >        <touch file="work/b" />
> >
> >        <jar jarfile="test.jar" update="true">
> >            <fileset dir="work" includes="**/*" />
> >        </jar>
> >
> >        <!-- Use zip to add my manifest without having Ant -->
> >        <!-- try to merge with its default one, that is:   -->
> >        <!-- main/org/apache/tools/ant/defaultManifest.mf  -->
> >        <zip destfile="test.jar" basedir="work" update="true">
> >            <zipfileset dir="." includes="my_manifest"
> >                                fullpath="META-INF/MANIFEST.MF"/>
> >        </zip>
> >    </target>
> ></project>
> >
> >Thanks.
> >
> >--Cyril
> >
> >
> >-----Original Message-----
> >From: RADEMAKERS Tanguy [mailto:Tanguy.RADEMAKERS@swift.com]
> >Sent: Thursday, June 14, 2007 5:23 AM
> >To: Ant Users List
> >Subject: RE: replace an entry in a zip file?
> >
> >Hello Cyril,
> >
> >>GOAL:  To replace one entry in a zip file with an updated file.
> >>
> >>I cannot find an elegant way to do this, short of <unzip>'ing the
> >>archive, replacing the file of interest and then re-<zip>.  It seems
> >>there should be a better way.  Can anyone help?
> >>
> >>Thanks.
> >>
> >>--Cyril
> >
> >If you use the update attribute of the zip task - it will
> >"refresh" the zip with the file or files you send it, without
> >changing or removing the other files in the archive. You may
> >still need to extract the files of interest from the zip if
> >you don't have them elsewhere, but you don't need to explode
> >the whole zip just to change a few files.
> >
> >Regs,
> >/t
> >
> >---------------------------------------------------------------------
> >To unsubscribe, e-mail: user-unsubscribe@ant.apache.org For
> >additional commands, e-mail: user-help@ant.apache.org
> >
> >
> >---------------------------------------------------------------------
> >To unsubscribe, e-mail: user-unsubscribe@ant.apache.org
> >For additional commands, e-mail: user-help@ant.apache.org
> >
> >
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@ant.apache.org
> For additional commands, e-mail: user-help@ant.apache.org
>
>

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


RE: replace an entry in a zip file?

Posted by RADEMAKERS Tanguy <Ta...@swift.com>.
that's weird, i'm using 1.6.5 as well. 

I think we have a misunderstanding.

Here's what i did:

1) make three files a.txt, b.txt, c.txt, each with some text

2) create the following build.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project name="bollo" default="testzip" basedir=".">
    <target name="testzip">
        <zip destfile="txtfiles.zip" update="true">
            <fileset dir="." includes="*.txt"/>
        </zip>
    </target>
</project>

3) run that to get the first zip file: txtfiles.zip, containing the
three txt files listed above.

4) move b.txt and c.txt to b.bak and c.bak (so the zip task no longer
sees them) and update a.txt (add a string "updated")

5) re-run the build, and the updated zip archive txtfiles.zip now
contains the original versions of b.txt and c.txt, but the updated
version of a.txt.

In my book, that's equivalent to "replace one entry in a zip file with
an updated file", no?

/t

>-----Original Message-----
>From: Cyril Sagan [mailto:Cyril.Sagan@sas.com] 
>Sent: Thursday, June 14, 2007 6:12 PM
>To: Ant Users List
>Subject: RE: replace an entry in a zip file?
>
>Thanks for your reponse.  However, this does not work for me 
>in Ant 1.6.5.
>Note that my goal is to *replace* a file that's already in the zip.
>
>Seems like the best solution would be for the duplicate 
>attribute to support a "replace" option.
>
>FWIW, I'm doing this to control my jar manifest.  I can't use 
><jar> because Ant merges with its default manifest.  I'm 
>having a hard time employing this advice from the Ant doc:
>
>http://ant.apache.org/manual/CoreTasks/manifest.html
>
>    If you find that Ant generates manifests incompatible with your
>    runtime, take a manifest it has built, fix it up however you need
>    and switch to using the <zip>  task to create the JAR, feeding in
>    the hand-crafted manifest.
>
>Here's my build.xml:
>
><?xml version="1.0"?>
><project name="manifest_test" default="go">
>
>    <target name="go">
>        <!-- build trivial sample jar -->    
>        <mkdir dir="work" />
>        <touch file="work/a" />
>        <touch file="work/b" />
>
>        <jar jarfile="test.jar" update="true">
>            <fileset dir="work" includes="**/*" />
>        </jar>
>
>        <!-- Use zip to add my manifest without having Ant -->
>        <!-- try to merge with its default one, that is:   -->
>        <!-- main/org/apache/tools/ant/defaultManifest.mf  -->
>        <zip destfile="test.jar" basedir="work" update="true">
>            <zipfileset dir="." includes="my_manifest"
>                                fullpath="META-INF/MANIFEST.MF"/>
>        </zip>
>    </target>
></project>
>
>Thanks.
>
>--Cyril
>
>
>-----Original Message-----
>From: RADEMAKERS Tanguy [mailto:Tanguy.RADEMAKERS@swift.com] 
>Sent: Thursday, June 14, 2007 5:23 AM
>To: Ant Users List
>Subject: RE: replace an entry in a zip file?
>
>Hello Cyril,
>
>>GOAL:  To replace one entry in a zip file with an updated file.
>>
>>I cannot find an elegant way to do this, short of <unzip>'ing the 
>>archive, replacing the file of interest and then re-<zip>.  It seems 
>>there should be a better way.  Can anyone help?
>>
>>Thanks.
>>
>>--Cyril
>
>If you use the update attribute of the zip task - it will 
>"refresh" the zip with the file or files you send it, without 
>changing or removing the other files in the archive. You may 
>still need to extract the files of interest from the zip if 
>you don't have them elsewhere, but you don't need to explode 
>the whole zip just to change a few files.
>
>Regs,
>/t
>
>---------------------------------------------------------------------
>To unsubscribe, e-mail: user-unsubscribe@ant.apache.org For 
>additional commands, e-mail: user-help@ant.apache.org
>
>
>---------------------------------------------------------------------
>To unsubscribe, e-mail: user-unsubscribe@ant.apache.org
>For additional commands, e-mail: user-help@ant.apache.org
>
>

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


Re: replace an entry in a zip file?

Posted by Peter Reilly <pe...@gmail.com>.
Your build file *nearly* works!
You are been defeated by the timestamp check.
Zip  will only update a zip file with files that are
newer that the files that are in the zip file.
For the manual page:

"""
Please note that ZIP files store file modification times with a
granularity of two seconds. If a file is less than two seconds newer
than the entry in the archive, Ant will not consider it newer.
"""

There does not seem to be "force" attribute to get the zip task
to ALWAYS update the file.

Using the update option and multiple adding of files to zip/jar
files are always problematic. (For example, What to do with deleted files)
I would suggest that you should refactor your build file so
that you just have one zip task (per jar file). for example:
   <target name="go">
       <!-- build trivial sample jar -->
       <mkdir dir="work" />
       <touch file="work/a" />
       <touch file="work/b" />

       <zip destfile="test.jar">
           <fileset dir="work" includes="**/*" />
           <zipfileset dir="." includes="my_manifest"
                               fullpath="META-INF/MANIFEST.MF"/>
       </zip>
   </target>

Peter

On 6/14/07, Cyril Sagan <Cy...@sas.com> wrote:
> Thanks for your reponse.  However, this does not work for me in Ant 1.6.5.
> Note that my goal is to *replace* a file that's already in the zip.
>
> Seems like the best solution would be for the duplicate attribute to support a "replace" option.
>
> FWIW, I'm doing this to control my jar manifest.  I can't use <jar> because Ant merges with its default manifest.  I'm having a hard time employing this advice from the Ant doc:
>
> http://ant.apache.org/manual/CoreTasks/manifest.html
>
>     If you find that Ant generates manifests incompatible with your
>     runtime, take a manifest it has built, fix it up however you need
>     and switch to using the <zip>  task to create the JAR, feeding in
>     the hand-crafted manifest.
>
> Here's my build.xml:
>
> <?xml version="1.0"?>
> <project name="manifest_test" default="go">
>
>     <target name="go">
>         <!-- build trivial sample jar -->
>         <mkdir dir="work" />
>         <touch file="work/a" />
>         <touch file="work/b" />
>
>         <jar jarfile="test.jar" update="true">
>             <fileset dir="work" includes="**/*" />
>         </jar>
>
>         <!-- Use zip to add my manifest without having Ant -->
>         <!-- try to merge with its default one, that is:   -->
>         <!-- main/org/apache/tools/ant/defaultManifest.mf  -->
>         <zip destfile="test.jar" basedir="work" update="true">
>             <zipfileset dir="." includes="my_manifest"
>                                 fullpath="META-INF/MANIFEST.MF"/>
>         </zip>
>     </target>
> </project>
>
> Thanks.
>
> --Cyril
>
>
> -----Original Message-----
> From: RADEMAKERS Tanguy [mailto:Tanguy.RADEMAKERS@swift.com]
> Sent: Thursday, June 14, 2007 5:23 AM
> To: Ant Users List
> Subject: RE: replace an entry in a zip file?
>
> Hello Cyril,
>
> >GOAL:  To replace one entry in a zip file with an updated file.
> >
> >I cannot find an elegant way to do this, short of <unzip>'ing the
> >archive, replacing the file of interest and then re-<zip>.  It seems
> >there should be a better way.  Can anyone help?
> >
> >Thanks.
> >
> >--Cyril
>
> If you use the update attribute of the zip task - it will "refresh" the zip with the file or files you send it, without changing or removing the other files in the archive. You may still need to extract the files of interest from the zip if you don't have them elsewhere, but you don't need to explode the whole zip just to change a few files.
>
> Regs,
> /t
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@ant.apache.org For additional commands, e-mail: user-help@ant.apache.org
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@ant.apache.org
> For additional commands, e-mail: user-help@ant.apache.org
>
>

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


RE: replace an entry in a zip file?

Posted by Cyril Sagan <Cy...@sas.com>.
Thanks for your reponse.  However, this does not work for me in Ant 1.6.5.
Note that my goal is to *replace* a file that's already in the zip.

Seems like the best solution would be for the duplicate attribute to support a "replace" option.

FWIW, I'm doing this to control my jar manifest.  I can't use <jar> because Ant merges with its default manifest.  I'm having a hard time employing this advice from the Ant doc:

http://ant.apache.org/manual/CoreTasks/manifest.html

    If you find that Ant generates manifests incompatible with your
    runtime, take a manifest it has built, fix it up however you need
    and switch to using the <zip>  task to create the JAR, feeding in
    the hand-crafted manifest.

Here's my build.xml:

<?xml version="1.0"?>
<project name="manifest_test" default="go">

    <target name="go">
        <!-- build trivial sample jar -->    
        <mkdir dir="work" />
        <touch file="work/a" />
        <touch file="work/b" />

        <jar jarfile="test.jar" update="true">
            <fileset dir="work" includes="**/*" />
        </jar>

        <!-- Use zip to add my manifest without having Ant -->
        <!-- try to merge with its default one, that is:   -->
        <!-- main/org/apache/tools/ant/defaultManifest.mf  -->
        <zip destfile="test.jar" basedir="work" update="true">
            <zipfileset dir="." includes="my_manifest"
                                fullpath="META-INF/MANIFEST.MF"/>
        </zip>
    </target>
</project>

Thanks.

--Cyril


-----Original Message-----
From: RADEMAKERS Tanguy [mailto:Tanguy.RADEMAKERS@swift.com] 
Sent: Thursday, June 14, 2007 5:23 AM
To: Ant Users List
Subject: RE: replace an entry in a zip file?

Hello Cyril,

>GOAL:  To replace one entry in a zip file with an updated file.
>
>I cannot find an elegant way to do this, short of <unzip>'ing the 
>archive, replacing the file of interest and then re-<zip>.  It seems 
>there should be a better way.  Can anyone help?
>
>Thanks.
>
>--Cyril

If you use the update attribute of the zip task - it will "refresh" the zip with the file or files you send it, without changing or removing the other files in the archive. You may still need to extract the files of interest from the zip if you don't have them elsewhere, but you don't need to explode the whole zip just to change a few files.

Regs,
/t

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


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


RE: replace an entry in a zip file?

Posted by RADEMAKERS Tanguy <Ta...@swift.com>.
Hello Cyril,

>GOAL:  To replace one entry in a zip file with an updated file.
>
>I cannot find an elegant way to do this, short of <unzip>'ing the
>archive, replacing the file of interest and then re-<zip>.  It seems
>there should be a better way.  Can anyone help?
>
>Thanks.
>
>--Cyril

If you use the update attribute of the zip task - it will "refresh" the
zip with the file or files you send it, without changing or removing the
other files in the archive. You may still need to extract the files of
interest from the zip if you don't have them elsewhere, but you don't
need to explode the whole zip just to change a few files.

Regs,
/t

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