Ant Tar task doesn’t care about your file permissions
According to the documentation for the Ant Tar task, the “implicit fileset” of stuff to be included in your archive can be extended “to allow control over the access mode, username and groupname.” I guess you have to read between the lines (or go with the ol’ trial by error) to find out that not only does the implicit fileset provide no control over these properties of your files, it actively reverts the file permissions to some default access mode (644). Java ftw!
So you are hypothetically deploying your ant-built tar’d up software release. Let’s further say for the sake of argument that it contains some business-critical scripts that must keep their executable mode to be run from cron. Oops, those files are no longer executable! You will soon be disappointed at the failure of your cron job to do anything at all, and you may experience some increased email volume accompanied by mild irritation. If this condition persists, call your doctor, or go back and RTFM again because as the docs imply, this shortcoming can be easily overcome.
Your job is to identify all the files that need to keep their mode, username, or groupname, and specify said property in a special fileset called tarfileset. In my ant build, let’s say the build root is ${builddir} and contains 2 components called src and lib. I’ve got one specific file src/foo/exec.sh, and a whole tree of stuff at lib/bar, that have to be executable. I will need to call the Tar task with two tarfilesets: one to include the executables and set their mode, and a second to include everything else while excluding the executables.
Before:
<tar destfile="${buildfile.name}"
basedir="${builddir}"
longfile="gnu"
includes="src/**, lib/**"/>
After:
<tar destfile="${buildfile.name}" longfile="gnu">
<tarfileset dir="${builddir}" filemode="755">
<include name="src/foo/exec.sh"/>
<include name="lib/bar/**"/>
</tarfileset>
<tarfileset dir="${builddir}">
<include name="src/**"/>
<include name="lib/**"/>
<exclude name="src/foo/exec.sh"/>
<exclude name="lib/bar/**"/>
</tarfileset>
</tar>
Works for me!
A useful trick for this is to use a combination of a selector and a patternset. The patternset defines all the files you want to include and the selector defines the subset of these files that need to have execute permission:
Now you can do:
It’s probably not worth doing this for this simple example, but for more complex patterns and selectors it’s a very useful approach.
A useful trick for this is to use a combination of a selector and a patternset. The patternset defines all the files you want to include and the selector defines the subset of these files that need to have execute permission:
<![CDATA[
]]>
Now you can do:
<![CDATA[
]]>
It’s probably not worth doing this for this simple example, but for more complex patterns and selectors it’s a very useful approach.
Third time lucky – why does it have to be so hard to post angle brackets in a blog comment…
A useful trick for this is to use a combination of a selector and a patternset. The patternset defines all the files you want to include and the selector defines the subset of these files that need to have execute permission:
<patternset id=”all.files”>
<include name=”src/**”/>
<include name=”lib/**”/>
</patternset>
<selector id=”executable.files”>
<or>
<filename name=”src/foo/exec.sh” />
<filename name=”lib/bar/**” />
</or>
</selector>
Now you can do:
<tar destfile=”${buildfile.name}” longfile=”gnu”>
<tarfileset dir=”${builddir}” filemode=”755″>
<patternset refid=”all.files” />
<selector refid=”executable.files” />
</tarfileset>
<tarfileset dir=”${builddir}”>
<patternset refid=”all.files” />
<not><selector refid=”executable.files” /></not>
</tarfileset>
</tar>
It’s probably not worth doing this for this simple example, but for more complex patterns and selectors it’s a very useful approach.
Gold Star!