ant - how to get a zero resource count if the folder does not exist - ant

I'm trying to base a task on whether a folder has content, not on whether it merely exists. I know there is probably a long winded solution, is there a better solution that I'm missing ?
I've tried two different methods to set a property depending on whether or not a folder has files in it.
My understanding is that 'available' does not permit wildcards like:
<available property="has.test.data" file="${test.data.dir}/**" type="file"/>
I tried this but it does not work if the folder (test.data.dir) does not exist:
<fileset id="test.data.files" dir="${test.data.dir}" includes="**/*" />
<condition property="has.test.data">
<resourcecount when="greater" count="0"> <fileset refid="test.data.files" /> </resourcecount>
</condition>
Ideally, I want to base a task on whether the folder actually has content, not just an empty folder.

You can use erroronmissingdir="false", to avoid the error for a non-existing directory. Add else="false" if you need the property to always exist
<?xml version="1.0" encoding="utf-8"?>
<project name="Test resourcecount" xmlns:if="ant:if">
<fileset id="test.data.files" dir="${test.data.dir}" includes="**/*" erroronmissingdir="false"/>
<condition property="has.test.data" else="false">
<resourcecount when="greater" count="0"> <fileset refid="test.data.files" /> </resourcecount>
</condition>
<echo if:true="${has.test.data}">${test.data.dir} is exists and is not empty</echo>
</project>
related Ant: How can I ignore build error if directory doesn't exist?

Related

Ant task: add a file to an archive with a parameter

everyone!
I'm currently struggling with an Ant task for a DITA plugin. It would consist in adding a file (whatever the extension is) to an archive via the command line. The idea is to set a parameter like this :
dita -f mymap.ditamap -transtype htmlCustom -Dadd-file=fileOfMyChoice.txt
The part that interests me is the last one: -Dadd-file=fileOfMyChoice.txt
So far, I've tried to include two choices into my target.
The user sets a add-file parameter and its value is added into the fileset with the base set of generated files.
Or, nothing is passed via this parameter and the base set of generated files is included in the fileset.
The part that is still challenging to me if the one that identifies if a parameter add-file is passed and how its value is transmitted in a fileset.
If you have any pointers for me, that would be awesome.
<target name="map2exportmap">
<dirname property="dita.temp.dir.fullpath" file="${dita.temp.dir}${file.separator}dummy.file"/>
<xslt in="${dita.temp.dir.fullpath}${file.separator}.job.xml"
out="${dita.temp.dir.fullpath}${file.separator}allResources.out"
style="${dita.plugin.com.myplugin.dir}/xsl/generateAllResources.xsl"
force="true"/>
<mkdir dir="${dita.map.output.dir}/temp"/>
<fileset id="global" dir="${user.input.dir}/" includesfile="${dita.temp.dir.fullpath}${file.separator}allResources.out" />
<union id="globalAddendum">
<fileset id="ditaGeneration" dir="${user.input.dir}/" includesfile="${dita.temp.dir.fullpath}${file.separator}allResources.out"/>
<fileset id="additionalFile" dir="${user.input.dir}/" includesfile="${add-File}"/>
</union>
<condition property="withAddedFile" refid="globalAddendum" else="global">
<isset property="add-file"/>
</condition>
<copy todir="${dita.map.output.dir}/temp">
<fileset dir="${user.input.dir}/" includesfile="${withAddedFile}"/>
</copy>
<zip destfile="${dita.map.output.dir}/${dita.map.filename.root}.zip">
<fileset dir="${dita.map.output.dir}/temp"/>
</zip>
<delete dir="${dita.map.output.dir}/temp"/>
</target>
everyone!
I found the solution!
Here is the code if it can help anyone.
<target name="map2exportmap">
<dirname property="dita.temp.dir.fullpath" file="${dita.temp.dir}${file.separator}dummy.file"/>
<xslt in="${dita.temp.dir.fullpath}${file.separator}.job.xml"
out="${dita.temp.dir.fullpath}${file.separator}allResources.out"
style="${dita.plugin.com.xxxxx.xxxxxxx.dir}/xsl/generateAllResources.xsl"
force="true"/>
<mkdir dir="${dita.map.output.dir}/temp"/>
<!-- Create two filesets depending on the argument `add-file` sent in the command line -->
<fileset id="base" dir="${user.input.dir}/" includesfile="${dita.temp.dir.fullpath}${file.separator}allResources.out" />
<fileset id="addedFile" file="${add-file}"/>
<!-- this is the core of the condition. It tests if there was an argument for `add-file, then ii sets the property `with.or.without.added.file`-->
<condition property="with.or.without.added.file" value="addedFile" else="base">
<isset property="add-file"/>
</condition>
<echo>${with.or.without.added.file}</echo>
<echo>${add-file}</echo>
<!-- Process the copy of content in the tempoerary folder-->
<copy todir="${dita.map.output.dir}/temp">
<fileset refid="${with.or.without.added.file}"/>
<fileset id="base" dir="${user.input.dir}/" includesfile="${dita.temp.dir.fullpath}${file.separator}allResources.out" />
</copy>
<!-- Execute the zip packaging -->
<zip destfile="${dita.map.output.dir}/${dita.map.filename.root}.zip">
<fileset dir="${dita.map.output.dir}/temp"/>
</zip>
<delete dir="${dita.map.output.dir}/temp"/>

Intentionally fail Ant build when using <delete> with a <fileset> including missing files

<delete includeEmptyDirs="false" failonerror="true">
<fileset dir="${dest.dir}" includes="a.txt,b.txt,c.abc"/>
</delete>
For example, if file a.txt is changed to a1.txt2 or something then Ant is not failing to find file. What to do?
That is not the purpose of failonerror attribute in this case.
From ant manual delete task :
Controls whether an error (such as a failure to delete a file)
stops the build or is merely reported to the screen. Only relevant if
quiet is "false".
It's not an error, if fileset doesn't match.
Also you don't need to set failonerror=true as it is default.
To make it fail, use fail with condition and resourcecount, f.e.:
<delete includeEmptyDirs="false" failonerror="true">
<fileset dir="${dest.dir}" includes="a.txt,b.txt,c.abc" id="foobar"/>
</delete>
<fail message="Fileset doesn't match !">
<condition>
<resourcecount when="eq" count="0">
<fileset refid="foobar"/>
</resourcecount>
</condition>
</fail>

How to create a list of available files from a list of file names in a property in Ant?

I have a property with a list of jars delimited with semicolons. The contents of the property is read from a file and not part of the build file, but it looks like this:
<property name="jars" value="a.jar;b.jar;c.jar"/>
And I would like to check if all the files are available. I know how to do it manually using:
<target name="opt">
<echo message="jars: ${jars}"/>
<condition property="found">
<and>
<available file="a.jar"/>
<available file="b.jar"/>
<available file="c.jar"/>
</and>
</condition>
<echo message="found: ${found}"/>
</target>
But how can this be done if the list of files is in a property and can not be written into the build file?
I need something like "apply and map available files". How can this be done?
You can use pathconvert to convert your file string to a fileset-include-pattern which can be used in a fileset; e.g.:
<pathconvert property="includespattern" pathsep=",">
<path path="a.jar;b.jar;c.jar;nonexisting.jar" />
<globmapper from="${basedir}/*" to="*" handledirsep="true" />
</pathconvert>
<fileset id="your.fileset" dir="${basedir}" includes="${includespattern}"/>
<!-- fileset will only contain existing files -->
<echo>${toString:your.fileset}</echo>

ant: how to compare contents of two files

I want to compare the contents of two files (say file1.txt,file2.txt) using ANT.
if files content are same then it should set some 'property' to true, if contents are not same then it should set the 'property' as false.
Can anyone suggest me any ANT task that can do this.
Thanks in advance.
You can use something like:
<condition property="property" value="true">
<filesmatch file1="file1"
file2="file2"/>
</condition>
This will set the property only if the files are the same.
You can then check for the property, using
<target name="foo" if="property">
...
</target>
This is available in ant, with no added dependency, see here for other conditions.
I am in the same situation to compare two files and switch into different targets depending on files match or files mismatch...
Heres the code:
<project name="prospector" basedir="../" default="main">
<!-- set global properties for this build -->
<property name="oldVersion" value="/code/temp/project/application/configs/version.ini"></property>
<property name="newVersion" value="/var/www/html/prospector/application/configs/version.ini"></property>
<target name="main" depends="prepare, runWithoutDeployment, startDeployment">
<echo message="version match ${matchingVersions}"></echo>
<echo message="version mismatch ${nonMatchingVersion}"></echo>
</target>
<target name="prepare">
<!-- gets true, if files are matching -->
<condition property="matchingVersions" value="true" else="false">
<filesmatch file1="${oldVersion}" file2="${newVersion}" textfile="true"/>
</condition>
<!-- gets true, if files are mismatching -->
<condition property="nonMatchingVersion" value="true" else="false">
<not>
<filesmatch file1="${oldVersion}" file2="${newVersion}" textfile="true"/>
</not>
</condition>
</target>
<!-- does not get into it.... -->
<target name="startDeployment" if="nonMatchingVersions">
<echo message="Version has changed, update gets started..."></echo>
</target>
<target name="runWithoutDeployment" if="matchingVersions">
<echo message="Version equals, no need for an update..."></echo>
</target>
The properties are correct and change on changing file contents.
the task for nonMatchingVersions never gets started.

Ant check existence for a set of files

In ant, how can i check if a set of files (comma-separated list of paths) exist or not?
For example I need to check if all paths listed in myprop exist and if so i want to set a property pathExist:
<property name="myprop" value="path1,path2,path3"/>
So in the example all of path1 path2 path3 must exist to set pathExist to true, otherwise false.
I discovered that for a single resource I can use the resourceexist task, but i can't figure out how to use that with a comma-separated list of paths.
How can I check the existence for a set of paths? Thanks!
You can use a combination of a filelist, restrict and condition task for this.
In the below example a filelist is created from the property with the comma-separated list of files. Using restrict a list of the files that don't exist is found. This is placed in a property which will be empty if all the files are found.
<property name="myprop" value="path1,path2,path3"/>
<filelist id="my.files" dir="." files="${myprop}" />
<restrict id="missing.files">
<filelist refid="my.files"/>
<not>
<exists/>
</not>
</restrict>
<property name="missing.files" refid="missing.files" />
<condition property="pathExist" value="true" else="false">
<length string="${missing.files}" length="0" />
</condition>
<echo message="Files all found: ${pathExist}" />
You could use something like this to generate a failure message listing the missing files:
<fail message="Missing files: ${missing.files}">
<condition>
<length string="${missing.files}" when="greater" length="0" />
</condition>
</fail>
Bundled conditions are the shortest solution to check for existence of multiple dirs or files :
<condition property="pathExist">
<and>
<available file="/foo/bar" type="dir"/>
<available file="/foo/baz" type="dir"/>
<available file="path/to/foobar.txt"/>
...
</and>
</condition>
To check for a commaseparated list of path use Ant addon Flaka , f.e. :
<project xmlns:fl="antlib:it.haefelinger.flaka">
<!-- when you have a cvs property use split function
to get your list to iterate over -->
<property name="checkpath" value="/foo/bar,/foo/baz,/foo/bazz"/>
<fl:for var="file" in="split('${checkpath}', ',')">
<fl:fail message="#{file} does not exist !!" test="!file.tofile.exists"/>
</fl:for>
</project>
Another possibility is the use of scriptcondition task with a jvm scripting language like groovy,beanshell .. etc.
This can be solved with the set operations of Ant´s resource collections. If you calculate the intersection of the list of required files with the list of existing files it must not differ from the list of required files. This shows how to do it:
<property name="files" value="a.jar,b.jar,c.jar"/>
<target name="missing">
<condition property="missing">
<resourcecount when="ne" count="0">
<difference id="missing">
<intersect>
<filelist id="required" dir="." files="${files}"/>
<fileset id="existing" dir="." includes="*.jar"/>
</intersect>
<filelist refid="required"/>
</difference>
</resourcecount>
</condition>
</target>
<target name="check" depends="missing" if="missing">
<echo message="missing: ${toString:missing}"/>
</target>
The check target reports the list of missing files only if a file is missing.

Resources