How can we use search for a file under particular directory in ant - ant

Hi all this is my code for checking if a particular file is present e.g. ${file}=license
<target name="File.check" >
<condition property="File.exists" >
<available file="${File}" type="file" />
</condition>
although if the file present is exactly license it works fine but sometimes the file can be either license.txt or even in uppercase also.
So I want my above code to work under all conditions even if the file is License or LICENSE or license or LICENSE.txt or anything that starts with l or L.

It probably would be easiest to include all possible variations, as the file attribute needs a real file and does not allow wildcards:
<condition property="File.exists" >
<or>
<available file="license.txt" type="file" />
<available file="LICENSE.txt" type="file" />
<available file="license" type="file" />
<available file="LICENSE" type="file" />
</or>
</condition>
The other possibility is to write your own condition.

You could use the Contains condition to check whether ${file} contains the text "license". It even has a casesensitive argument. Not sure whether
anything that starts with l or L
is a good idea though.

<target name="SearchForfile">
<delete dir="../filepresent" />
<copy todir="../filepresent" failonerror="yes" flatten="true">
<fileset dir="../result/unzip/${param1}" casesensitive="false">
<include name="**/*license*"/>
</fileset>
</copy>
<antcall target="CheckFileExistance"/>
</target>
in that "CheckFileExistance" target just check if "filepresent" folder is present or not if it is then the file is present in your source directory and else if "filepresent" folder is not there that means file is not present anywhere in your search directory...i hope this makes everything clear

Related

Ant: If property contains certain string, change the name of the property

I am trying to check a folder's name, and if it contains a certain string, I want that folder path to be changed.
So far I came up with this:
<property name="component.release.dir" value="${install.dir}/${component.name}" />
<!-- Check if the component is a part of projectL -->
<condition property="projectLFolderSpotted">
<matches pattern="projectL" string="${component.release.dir}"/>
<!-- if so, put the component in an appropriate folder -->
<property name="component.release.dir" value="${install.dir}/projectL/${component.name}" />
<echo message="projectL component has been detected, and moved accordingly!"/>
</condition>
But I get the following error:
condition doesn't support the nested "property" element.
Is there a way to achieve this?
Thanks in advance.
Properties in ANT are immutable, once they're assigned a value it doesn't change.
Here's how I'd suggest you do it:
<project name="demo" default="build">
<property name="release.dir.seed" location="build/helloworld"/>
<condition property="release.dir" value="build/found/helloworld" else="build/notfound/helloworld">
<contains string="${release.dir.seed}" substring="helloworld"/>
</condition>
<target name="build">
<echo message="Result: ${release.dir}"/>
</target>
</project>

Set ant property when comparing directories

I have two directories that I need to compare for having same files. I succesfully do this as follows:
<fileset dir="d:\test" id="onlyinbar">
<not>
<present targetdir="A_DIR"/>
</not>
</fileset>
<echo>these files are only in bar : ${toString:onlyinbar}</echo>
<fileset dir="A_DIR" id="differentbarfoo">
<different targetdir="d:\test" ignoreFileTimes="true"/>
</fileset>
<echo>these files are different in bar compared to foo : ${toString:differentbarfoo}</echo>
However, I need to issue an other task if either of these are true. So long the <condition> tag does seem to support only file to file comparison and I cannot see how to assign a property within the <fileset> tag. Help will be appreciated.
We needed to avoid any third party contribs for this solution. My major problem was the combination of the tags. We knew that our "tests" i.e fileset tags had to be in the condition but didn't know how. The resourcecount though short out the issue:
<target name="export-report-icons" description="A description">
<condition property="test2" else="false">
<or>
<resourcecount when="gt" count="0" property="flength">
<fileset dir="d:\test" id="onlyinbar">
<present targetdir="DIRs_A" present="srconly"/>
</fileset>
</resourcecount>
<resourcecount when="gt" count="0" property="flength">
<fileset dir="DIR_A" id="differentbarfoo">
<different targetdir="d:\test" ignoreFileTimes="true"/>
</fileset>
</resourcecount>
</or>
</condition>
</target>
<target name="copyThis" depends="export-report-icons" if="${test2}">
....
</target>
So what this does, sets an OR for the case that one of the two filesets succeeds, the counter wraps the fileset resource so that it can be hosted under the condition and the condition has a property true or false depending on ORed counts. The "copy-This" target executes if the ${test2} is true. Please note that if you set id=test2 it will always qualify as true as in this case it checks for value presence.
The <union> set operator groups resources from multiple collections into one collection.
Similarly, take a look at <intersect> and <difference>.
You mention "if", which I assume refers to the <if> task from the third-party Ant-Contrib library. Here's an example that echoes if the filesets combined by <union> match any files:
<if>
<resourcecount when="gt" count="0">
<union id="Check">
<resources refid="onlyinbar"/>
<resources refid="differentbarfoo"/>
</union>
</resourcecount>
<then>
<echo>There are differences: ${toString:Check}</echo>
</then>
</if>

How to identify if a file is copied from a particular archive?

I am new to ANT.
I have a very specific scenario to handle in this:
STEP-1: I need to look for the pattern of filenames in certain ear files. If the pattern matches then I need to extract those files.
STEP-2: And if any file is extracted from a certain ear (similar to zip-file) file, then I need to search for another set of files, and copy those set of files too.
The case to handle is "How to identify if a file is copied from a particular archive" if found then proceed to step 2, else move to next archive.
I have achieved STEP-1 but no idea how to achieve step-2.
STEP-1
<!-- Set via arguments passed -->
<patternset id="pattern.needtocopy" includes="${needtocopyfile.pattern}" excludes="${ignore.pattern}">
</patternset>
<target name="get-binaries-from-baseline">
<for param="binary">
<path>
<fileset dir="${baseline.dir}/target/aaa/bbb/ccc" includes="*.ear" />
</path>
<sequential>
<basename file="#{binary}" property="#{binary}.basename" />
<unzip src="#{binary}" dest="${baseline.dir}">
<patternset refid="pattern.needtocopy" />
<mapper type="flatten" />
</unzip>
</sequential>
</for>
</target>
STEP-2:
????
Need help in this.
Thanks.
Well I resolved the same, using a groovy script based on the resources I could find.
<target name="findJars">
<zipfileset id="found" src="${ear-name}">
<patternset refid="${patternsetref}" />
</zipfileset>
<groovy>
project.references.found.each {
println it.name
println project.properties.'ear-name'
println project.properties.'dest.dir'
}
</groovy>
</target>
And then I added another task which takes this filename and ear-file-name as input and extracts the related jars based on file to search pattern.

Ant: Conditional Copy

I want to overwrite the hosts file on the Windows machine if the user allows it:
<input message="Do you want to overwrite the HOSTS file?"
addproperty="overwrite.hosts" validargs="yes,no" />
<copy tofile="${env.WINDIR}/system32/drivers/etc/hosts.backup">
<fileset file="${env.WINDIR}/system32/drivers/etc/hosts" />
</copy>
<copy todir="${env.WINDIR}/system32/drivers/etc">
<fileset file="${trainer.dir}/hosts" />
</copy>
How do I do the copies only if the user says yes?
EDIT:
I tried this:
<input message="Do you want to overwrite the HOSTS file?" addproperty="overwrite.hosts" validargs="yes,no" />
<if>
<equals arg1="${overwrite.hosts}" arg2="yes" />
<then>
<copy tofile="${env.windir}/system32/drivers/etc/hosts.backup">
<fileset file="${env.windir}/system32/drivers/etc/hosts">
</fileset>
</copy>
<copy todir="${env.windir}/system32/drivers/etc">
<fileset file="${trainer.dir}/hosts">
</fileset>
</copy>
</then>
</if>
and I get this output:
C:\trainer\build.xml:16: Problem: failed to create task or type if
Cause: The name is undefined.
Action: Check the spelling.
Action: Check that any custom tasks/types have been declared.
Action: Check that any <presetdef>/<macrodef> declarations have taken place.
I'm an ant rookie... What do I need to do?
You could use a condition or a if task for that. (The latter is part of the ant-contrib project.)
You can use an "if" parameter on a target to make it conditional on the property being set.
I've never used the "input" task -- I didn't know it existed until just now (thanks for the heads up!) -- but a quick look at the documentation indicates that it sets the named property to the value entered, i.e. after an "input" the property is always set. So I guess you would need a "condition" to test the value and set or not set some other property.
Something like this. I just ran a quick test and this does work. Namely, if you answer the question "y" it prints the message, and if you answer "n" it does not.
<project name="test" default="do.whatever">
<target name="decide.do.whatever">
<input message="So you wanna do this or not?" validargs="y,n" addproperty="wanna"/>
<condition property="wanna.yes">
<equals arg1="${wanna}" arg2="y"/>
</condition>
</target>
<target name="do.whatever" depends="decide.do.whatever" if="wanna.yes">
<echo message="Yeah he wannas."/>
</target>
</project>

Make Ant's delete task fail when a directory exists and is not deleted but not when it doesn't exist at all

I have the following clean function in my build script and I'd like to know how I can improve it.
<target name="clean" description="Clean output directories.">
<!-- Must not fail on error because it fails if directories don't exist.
Is there really no better way to do this? -->
<delete includeEmptyDirs="true" failonerror="false">
<fileset dir="${main.build.directory}" />
<fileset dir="dist" />
<fileset dir="${documentation.build.directory}" />
<fileset dir="/build-testing" />
</delete>
</target>
Specifically regarding my comment, I'm unhappy with the fact that I can't run this on a fresh box because the directory structure hasn't been set up yet by the other targets. We run the build in such a way that it entirely recreates the structures necessary for testing and deployment every time to avoid stale class files and such. With the way that delete currently is set up, a failure to delete a file does not fail the build and I'd like it to. I don't want it to fail the build if the file doesn't exist though. If it doesn't exist then what I'm asking it to do has already happened.
Thoughts?
via Michael's answer, which was 90% of what I needed but not quite all the way there.
The actual solution that I ended up with because of your answers is the following:
<target name="clean" description="Clean output directories.">
<!-- Must not fail on error because it fails if directories don't exist.
Is there really no better way to do this? -->
<delete includeEmptyDirs="true" failonerror="false">
<fileset dir="${main.build.directory}" />
...
</delete>
<available
file="${main.build.directory}"
type="dir"
property="delete-main-failure" /> ...
<condition property="delete-failure">
<and>
<isset property="delete-main-failure" /> ...
</and>
</condition>
<fail
if="delete-failure"
message="Unable to delete previous build's directories." />
</target>
This meets my criteria that the code attempts to delete it and then fails if it still exists. It's super ugly though. The default behavior of the delete task strikes me as very odd. I suppose the rationale is that if you try to delete something and it isn't there then something must be wrong but it seems to me that the normal case would be that if it's not there you don't care because it's gone already while the odd case is that you needed it to be there but now it shouldn't be anymore at this specific stage in the build.
I came here to ask the same question... it doesn't look like there is an elegant way to solve this. When I want to keep the code clean, I do it this way:
<mkdir dir="${main.build.directory}" />
<delete dir="${main.build.directory}" failonerror="true" />
I didn't think the delete task had an "if" property. Will have to check that out.

Resources