Ant zip task will lost symbolic link? - ant

I used the below task to compress the folder to a zip file. But I found that the symbolic links in the folder lost when I unzipped the zip file.
<zip destfile="${file.path}">
<fileset dir="/tmp"/>
</zip>
For instance, previously, the file look like below.
lrwxrwxrwx 1 xxxx xxxx 25 Mar 15 21:02 libboost_atomic.so -> libboost_atomic.so.1.57.0
-rwxr-xr-x 1 xxxx xxxx 9135 Feb 8 04:46 libboost_atomic.so.1.57.0
After I compressed the folder using Ant and unzipped it, it look like below.
-rw-r--r-- 1 xxxx xxxx 9135 Feb 8 04:46 libboost_atomic.so
-rw-r--r-- 1 xxxx xxxx 9135 Feb 8 04:46 libboost_atomic.so.1.57.0

instead of the built-in zip command, try the using the exec and use
<exec executable="zip">
<arg value="--symlinks"/>
<arg value="-r"/>
<arg value="${file.path}"/>
<arg value="tmp"/>
</exec>
I tried the command line equivalent on mac and worked for me, please let me know on what system are you trying this.
Note, this requires you to have a 'zip' executable in your path (which I assume you do)

The zip format itself doesn't really support symbolic links in a portable way (and Ant doesn't support any of the not-so-portable options). Neither does Ant's tar task.

Related

Cannot execute gradle from the command line even though it's on my path

I have the following in ./bash_profile
export SRCROOT=/users/benjamin.beasley/work/svn/ccdev
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk_dev/Contents/Home
export PATH=$PATH$:~/tools/tools-versions/gradle-2.2.1/bin
export PATH=$PATH$:~/tools/activator
In ~/tools/tools-versions/gradle-1.12/bin, I do
drwxr-xr-x# 4 xxx.xxx WORKDAYINTERNAL\Domain Users 136 Nov 12 11:47 .
drwxr-xr-x# 13 xxx.xxx WORKDAYINTERNAL\Domain Users 442 Apr 29 2014 ..
-rwxr-xr-x# 1 xxx.xxx WORKDAYINTERNAL\Domain Users 5071 Apr 29 2014 gradle
-rwxr-xr-x# 1 xxx.xxx WORKDAYINTERNAL\Domain Users 2395 Apr 29 2014 gradle.bat
echo $PATH$:
/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/opt/X11/bin$:/Users/xxx.xxx/tools/tools-versions/gradle-2.2.1/bin$:/Users/xxx.xxx/tools/activator90566
so I get the gradle executable which is executable. I can execute it from this directory. But if I start a new shell, and type "gradle" it says command not found. But I "echo $PATH$" and I see that the full canonical path to the ~/tools/tools-versions/gradle-2.2.1/bin folder is there.
However I can execute activator which is an executable in the ~/tools/activator directory. I have no clue why bash knows about activator and not gradle.
In summary:
gradle is executable by this user
gradle can be run from the command line.
gradle is in the $PATH$ environment variable
other programs such as activator, which are also in $Path$ are executable anywhere in terminal regardless of directory which is what I want to be true of gradle.
Unix environment variables are $PATH not $PATH$ (they aren't like Windows env vars).
This is causing your problem.
This path is busted: /usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/opt/X11/bin$:/Users/xxx.xxx/tools/tools-versions/gradle-2.2.1/bin$:/Users/xxx.xxx/tools/activator90566
Notice the 90566 at the end? That's from $$ having been expanded to the current process id when you set the variable.
None of these are paths that actually exist or work:
/opt/X11/bin$
/Users/xxx.xxx/tools/tools-versions/gradle-2.2.1/bin$
/Users/xxx.xxx/tools/activator90566

Sign a launch4j executable in ant with sign4j and jsign

I have an application in a Jar and I wrap it in a exe with launch4j so is easy for the user to launch it (in windows). I have a certificate, so I sign the jar (I don't know if this is really necessary because it will be wrapped inside the exe) and I want to sign the exe but it corrupt the executable.
I use ant to make all the process and look like:
<signjar jar="${jar.location}" alias="${key.alias}" storetype="pkcs12" keystore="${key.file}" storepass="${key.password}" tsaurl="https://timestamp.geotrust.com/tsa" />
<launch4j configFile="launch4j_configuration.xml" fileversion="${version}.0" txtfileversion="${build}" productversion="${version}.0" txtproductversion="${build}" outfile="${exe.location}" jar="${jar.location}" />
<signexe file="${exe.location}" alias="${key.alias}" storetype="pkcs12" keystore="${key.file}" storepass="${key.password}" tsaurl="http://timestamp.verisign.com/scripts/timstamp.dll" />
I have found that is because when you sign the exe it broke the jar structure or something like this. But what I have also seen is that inside the launch4j folder is a sign4j folder that contains what I think is a program that solve this problem.
My problem now is how is used this program? And how can I integrate it in the ant script to sign the exe?
The README.txt file in the folder doesn't helped to me. Sorry if this so obvious but isn't clear for me. Also note that I'm using Ubuntu.
What I have found is that you must execute the sign4j command with the signing command as its argument. Something like:
sign4j jsign -s keyfile.p12 -a "(codesign_1091_es_sw_kpsc)" --storepass AVERYGOODPASSWORD --storetype pkcs12 -n MyProgram -u https://www.example.com MyProgram.exe
So, to integrate it into ant, you need to create an exec task. For example, something like:
<exec executable="sign4j">
<arg line="java -jar jsign-1.2.jar -s ${key.file} -a ${key.alias} --storepass ${key.password} --storetype pkcs12 ${exe.location}"/>
</exec>
It works also with other signing tools like for example authenticode from Microsoft, too ...
<exec executable="launch4j/sign4j/sign4j.exe">
<arg line="signtool.exe sign /fd SHA256 /f mycert.pfx /p foobar /t http://timestamp.verisign.com/scripts/timstamp.dll dist\myapp.exe"/>
</exec>
I use ant target as below to sign exe generated out of a jar file
<target name="signexe" depends="createExe" description="Signing Exe">
<exec executable="C:\Tools\Launch4j\sign4j\sign4j.exe">
<arg line="java -jar C:\3rdParty\jsign\jsign-3.1.jar
--keystore ${keystore.location} --alias ${key.alias} --storepass ${store.password}
--name 'Application Name'
--tsaurl http://timestamp.verisign.com/scripts/timstamp.dll
AppLauncher.exe"/>
</exec>
</target>

zipping a folder using ant

I want this folder structure to be zipped as it is-
Right now I am doing these steps-
Moving files other than folders to "Temp" folder.
Moving Folder1 to "Temp" folder.
Zipping Temp.
Deleting "Temp folder".
Is this the correct approach or is there any simple/better way of doing this?
There is no need to move the files before zipping them.
<zip destfile="test.zip" basedir="src_dir" includes="**/*"/>
If you had a more challenging selection to make than **/*, e.g. include and exclude specific files selectively, then you could achieve that with one or more filesets (or zipfilesets) within the zip element.
Here is the dir structure, including build.xml:
$ find .
.
./build.xml
./src_dir
./src_dir/Document.txt
./src_dir/Document2.txt
./src_dir/Document3.xml
./src_dir/Folder1
Here is the zip file created:
$ jar tvf test.zip
0 Fri Jul 20 08:36:06 GMT 2012 Folder1/
0 Fri Jul 20 08:36:26 GMT 2012 Document.txt
0 Fri Jul 20 08:36:12 GMT 2012 Document2.txt
0 Fri Jul 20 08:36:18 GMT 2012 Document3.xml

Combine zip archives in ANT with both filtering and case-sensativity

I want to combine several zip files together using ANT, but I've got three restrictions that cause the standard techniques to fail:
There are files (with known filenames) that I do not want included in the final archive.
Some of the source archives contain files with the same name, but different capitalization.
The machine that runs the script uses a case-insensitive filesystem.
To make my problem concrete, here's an example source archive. I do not know the file names represented by a.txt and A.txt, but I do know the filename b.txt.
$ touch a.txt ; zip src.zip a.txt ; rm a.txt
$ touch A.txt ; zip src.zip A.txt ; rm A.txt
$ touch b.txt ; zip src.zip b.txt ; rm b.txt
$ unzip -l src.zip
Archive: src.zip
Length Date Time Name
-------- ---- ---- ----
0 09-23-11 11:35 a.txt
0 09-23-11 11:35 A.txt
0 09-23-11 11:36 b.txt
-------- -------
0 3 files
And here's what I want: (everything from the original archive except b.txt)
$ ant
$ unzip -l expected.zip
Archive: expected.zip
Length Date Time Name
-------- ---- ---- ----
0 09-23-11 11:35 a.txt
0 09-23-11 11:35 A.txt
-------- -------
0 2 files
The two techniques that I've found recommended on the internet are:
<target name="unzip-then-rezip">
<!-- Either a.txt or A.txt is lost during unzip and
does not appear in out.zip -->
<delete dir="tmp"/>
<delete file="out.zip"/>
<mkdir dir="tmp"/>
<unzip src="src.zip" dest="tmp"/>
<zip destfile="out.zip" basedir="tmp" excludes="b.txt"/>
</target>
<target name="direct-zip">
<!-- Have not found a way to exclude b.txt from out.zip -->
<delete file="out.zip"/>
<zip destfile="out.zip">
<zipgroupfileset dir="." includes="*.zip" />
</zip>
</target>
Using unzip-then-rezip, I loose either a.txt or A.txt because the underlying filesystem is case-insensitive and can not store both files. Using direct-zip seems like the right way to go, but I have yet to find a way to filter out the files I don't want included.
I'm about to resort to creating my own ANT task to do the job, but I'd much rather use standard ANT tasks (or even ant-contrib), even if there's a performance or readability penalty.
I ended up creating a custom ANT task to solve the problem. The task accepts nested excludes elements which provide regular expressions that are matched against the entires in the source zip file.
As an added bonus, I was also able address another problem: renaming zip entries using regular expressions using a nested rename element.
The ANT code looks something like this:
<filter-zip srcfile="tmp.zip" tgtfile="target.zip">
<exclude pattern="^b\..*$"/>
<rename pattern="^HELLO/(.*)" replacement="hello/$1"/>
</filter-zip>
The kernel of the ANT task looks something like this:
zIn = new ZipInputStream(new FileInputStream(srcFile));
zOut = new ZipOutputStream(new FileOutputStream(tgtFile));
ZipEntry entry = null;
while ((entry = zIn.getNextEntry()) != null) {
for (Rename renameClause : renameClauses) {
...
}
for (Exclude excludeClause : excludeClauses) {
...
}
zOut.putNextEntry(...);
// Copy zIn to zOut
zOut.closeEntry();
zIn.closeEntry();
}
In my original question, I said I wanted to combine several zip files together. This is pretty straight forward using the 'direct-zip' method in the original question. I use this to create an intermediate zip file (tmp.zip) which I then use as the source to my filter-zip task:
<zip destfile="tmp.zip">
<zipgroupfileset dir="." includes="*.zip" />
</zip>
At the moment my filter-zip task runs a little slower then the zip (assemble all the zips) task... so the performance is (probably) pretty close to ideal. Combining the two steps together would be a nice little exercise, but not very high ROI for me.
Have a look at Ant's Resource Collections, especially things like restrict that allow you to filter files (and zip file contents etc.) in quite flexible ways.
This snippet seems to what you want (on my machine at least - OSX):
<project default="combine">
<target name="combine">
<delete file="expected.zip" />
<zip destfile="expected.zip">
<restrict>
<zipfileset src="src.zip" />
<not>
<name name="b.txt" />
</not>
</restrict>
</zip>
</target>
</project>
The input file:
$ unzip -l src.zip
Archive: src.zip
Length Date Time Name
-------- ---- ---- ----
0 09-24-11 00:55 a.txt
0 09-24-11 00:55 A.txt
0 09-24-11 00:55 b.txt
-------- -------
0 3 files
The output file:
$ unzip -l expected.zip
Archive: expected.zip
Length Date Time Name
-------- ---- ---- ----
0 09-24-11 00:55 A.txt
0 09-24-11 00:55 a.txt
-------- -------
0 2 files

How to execute an interactive application from Ant build script?

From http://ant.apache.org/manual/Tasks/exec.html :
Note that you cannot interact with the
forked program, the only way to send
input to it is via the input and
inputstring attributes. Also note that
since Ant 1.6, any attempt to read
input in the forked program will
receive an EOF (-1). This is a change
from Ant 1.5, where such an attempt
would block.
How do I launch and interact with interactive console program from ant?
What I want to do is similar to drush sqlc functionality, that is launch the mysql client interpreter using the proper database credentials, but not limited to this use case.
Here's a sample use case:
<project name="mysql">
<target name="mysql">
<exec executable="mysql">
<arg line="-uroot -p"/>
</exec>
</target>
</project>
When run using ant :
$ ant -f mysql.xml mysql
Buildfile: /home/ceefour/tmp/mysql.xml
mysql:
Enter password:
BUILD SUCCESSFUL
Total time: 2 seconds
After inputting password, it immediately exits.
Compare this with what happens when executing directly on the shell (expected behavior):
$ mysql -uroot -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 1122
Server version: 5.1.58-1ubuntu1 (Ubuntu)
Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
This software comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to modify and redistribute it under the GPL v2 license
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
You can launch your command via a shell, redirecting standard input/output/error from/to/to /dev/tty, which corresponds to the controlling terminal of the process.
<target name="dbshell" description="Open a shell for interactive tasks">
<exec executable="/bin/sh">
<arg value="-c"/>
<arg value="mysql -u root -p < /dev/tty > /dev/tty 2> /dev/tty"/>
</exec>
</target>
I have tried running on cosnole and if you do not fork it works.
As mentioned in the doc too.
Beside with eclipse there are additional ways to configure inputhandler.
As is acknowledged here.
http://www.coderanch.com/t/419646/tools/java-program-accept-user-input
A clean way to get this work
http://www.myeclipseide.com/PNphpBB2-viewtopic-t-25337.html

Resources