Execute ant task over sons of parent folder - ant

I was trying to execute a task over a fileset defined using something like this:
<target name="copyToTarget">
<copy todir="${target.folder}/" >
<fileset dir="../**/folder" />
</copy>
</target>
Is there anyway to achieve this?
EDIT:
I saw by myself I can use something like:
<fileset dir="../" includes="*/folder/** />
but the problem is that this copies the whole structure since the parent folder and I only need it contents (e.g., with this I obtain
/target/son1/folder/contents
and I'm looking for
/target/contents
EDIT 2:
Using How to strip one folder during Ant copy I managed how to get the result I need:
<target name="copyFolderToTarget">
<copy todir="${target.folder}" >
<fileset dir="../" includes="*/src_folder/**" />
<cutdirsmapper dirs="2"/>
</copy>
</target>

Related

Ant copy with exclusion pattern does not seem to work

The following Ant snippet should work:
...
<mkdir dir="${web.build.war.dir}/WEB-INF/classes"/>
<copy todir="${web.build.war.dir}/WEB-INF/classes">
<fileset dir="${web.build.classes.dir}">
<exclude name="**/pos/**" />
</fileset>
</copy>
...
It should copy every file from ${web.build.classes.dir} to ${web.build.war.dir}/WEB-INF/classes except those files that have /pos/ in their path.
But for some reason, when I do find build on the project, I get output that looks something like this:
...
build/war/WEB-INF/classes/my/path/to/pos
build/war/WEB-INF/classes/my/path/to/pos/Class1.class
build/war/WEB-INF/classes/my/path/to/pos/Class2.class
build/war/WEB-INF/classes/my/path/to/pos/Class3.class
build/war/WEB-INF/classes/my/path/to/pos/Class4.class
build/war/WEB-INF/classes/my/path/to/pos/Class5.class
build/war/WEB-INF/classes/my/path/to/pos/Class6.class
...
Every other similar copy operation appeared to work just fine.
Eh, in the end, the answer was quite obvious in hindsight.
In the original question I had omitted some of the tasks from the target for the sake of brevity. Appears, I should have not.
More complete snippet would have been this:
...
<mkdir dir="${web.build.war.dir}"/>
<copy todir="${web.build.war.dir}">
<fileset dir="${web.src.web.dir}">
<exclude name="**/pos/**"/>
<exclude name="security/**"/>
</fileset>
</copy>
<mkdir dir="${web.build.war.dir}/WEB-INF/classes"/>
<copy todir="${web.build.war.dir}/WEB-INF/classes">
<fileset dir="${web.build.classes.dir}">
<exclude name="**/pos/**" />
</fileset>
</copy>
...
The first copy task would copy all the resources from the development copy of the web resources to the war-to-be folder.
I was using Eclipse IDE and as the project was configured to build java classes to the ${web.src.web.dir}/WEB-INF/classes folder, the first task simply copied all of the classes to the war folder and thus the exclusion filter in the next copy task had no effect.

Loop through directory structure in ant

We want to loop through directory structure in ant without using foreach .
Is there any elegant way to do the same ?
The apply task can iterate over a set of directories or files
<target name="run-apply">
<apply executable="echo">
<dirset dir="src"/>
</apply>
</target>
I personally like the groovy ANT task
<target name="run-groovy">
<taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy"/>
<dirset id="dirs" dir="src"/>
<groovy>
project.references.dirs.each {
ant.echo it
}
</groovy>
</target>
The installation of the task jar is easily automated:
<target name="install-groovy">
<mkdir dir="${user.home}/.ant/lib"/>
<get dest="${user.home}/.ant/lib/groovy-all.jar" src="http://search.maven.org/remotecontent?filepath=org/codehaus/groovy/groovy-all/2.1.1/groovy-all-2.1.1.jar"/>
</target>
Finally if you're iterating thru other build files, the subant task is very useful:
<target name="run-subant">
<subant>
<fileset dir="src" includes="**/build.xml"/>
</subant>
</target>
Short answer: Not really. There are ways around this, but I prefer the ant-contrib <for/> task for clarity and simplicity. With the <local/> task, you can now localize values of variables. Before, you sometimes had to use ant-contrib's <var/> task to reset the values, so you could loop through them over and over.
<for param="directory">
<fileset dir="${some.dir}"/>
<sequential>
<local name="foo"/>
<local name="bar"/> <!-- Properties that may change with each iteration -->
<!-- Here be dragons -->
</sequential>
</for>
It's clean, simple, and easy to understand. The big issue many people have with Ant Contrib is that not everyone may have it installed in their $ANT_HOME/lib directory. Far enough. So, if you use ant-contrib, put it as part of your project.
I'll put the ant-contrib jar in ${basedir}/antlib/antcontrib and then put this in my program:
<taskdef resource="net/sf/antcontrib/antlib.xml">
<classpath>
<fileset dir="${basedir}/antlib/antcontrib"/>
</classpath>
</taskdef>
Now, when someone checks out my project, they have ant-contrib already installed (since it's inside my project) and accessible (since I point my <taskdef> task at the location of ant-contrib.jar in my project).

Using Ant to delete a file based on existence of another file

I need to write an ant task to selectively delete files.
In a directory, I have the following jars:
acme.jar
acme-201105251330.jar
I want to delete acme.jar because acme-*.jar exists.
Here's what I've tried:
<target name="-check-use-file">
<available property="file.exists">
<filepath> <fileset dir=".">
<include name="./test-*.jar"/> </fileset>
</filepath>
</available>
</target>
<target name="use-file" depends="-check-use-file" if="file.exists">
<!-- do something requiring that file... -->
</target>
Thanks
Have a look at If/Unless Attributes, examples given there seem to be exactly what you are looking for.

How can I process only files that have changed?

At the moment I'm doing this:
<delete dir="${RSA.dir}/file1" />
<copy todir="${RSA.dir}/file1" >
<fileset dir="${CLEARCASE.dir}/file1" />
</copy>
and repeating the same thing for other files - but it takes a long time.
I only want to delete and copy files that have been updated, with their modified date in clearcase later than that in RSA.
How can I do that?
Look into the sync task.
If you want to do it based on file contents, and ignore the timestamp, I think this macro will do that:
<macrodef name="mirror" description="Copy files only if different; remove files that do not exist in dir. This works similiar to robocopy /MIR." >
<attribute name="dir"/>
<attribute name="todir"/>
<sequential>
<copy overwrite="true" todir="#{todir}">
<fileset dir="#{dir}">
<different targetdir="${todir}"/>
</fileset>
</copy>
<delete includeemptydirs="true">
<fileset dir="#todir}">
<present targetdir="${dir}" present="srconly"/>
</fileset>
</delete>
</sequential>
</macrodef>
You need to use a selector on a FileSet. Something like this:
<fileset dir="${your.working.dir}/src/main" includes="**/*.java">
<different targetdir="${clean.clearcase.checkout}/src/main"
ignoreFileTimes="false"
ignoreContents="true" />
</fileset>
That compares your working dir to a clean checkout you have elsewhere, and returns the files whose last modified times have changed. You can use the fileset as the argument for a <delete> or a <copy>.

How do I "expand" an ant path (accessed with refId=..) to all files in the path except some?

I am trying to get ant4eclipse to work and I have used ant a bit, but not much above a simple scripting language. We have multiple source folders in our Eclipse projects so the example in the ant4eclipse documentation needs adapting:
Currently I have the following:
<target name="build">
<!-- resolve the eclipse output location -->
<getOutputpath property="classes.dir" workspace="${workspace}" projectName="${project.name}" />
<!-- init output location -->
<delete dir="${classes.dir}" />
<mkdir dir="${classes.dir}" />
<!-- resolve the eclipse source location -->
<getSourcepath pathId="source.path" project="." allowMultipleFolders='true'/>
<!-- read the eclipse classpath -->
<getEclipseClasspath pathId="build.classpath"
workspace="${workspace}" projectName="${project.name}" />
<!-- compile -->
<javac destdir="${classes.dir}" classpathref="build.classpath" verbose="false" encoding="iso-8859-1">
<src refid="source.path" />
</javac>
<!-- copy resources from src to bin -->
<copy todir="${classes.dir}" preservelastmodified="true">
<fileset refid="source.path">
<include name="**/*"/>
<!--
patternset refid="not.java.files"/>
-->
</fileset>
</copy>
</target>
The task runs successfully, but I cannot get the to work - it is supposed to copy all non-java files over too to emulate the behaviour of eclipse.
So, I have a pathId named source.path which contains multiple directories, which I somehow needs to massage into something the copy-task like. I have tried nesting which is not valid, and some other wild guesses.
How can I do this - thanks in advance.
You might consider using pathconvert to build a pattern that fileset includes can work with.
<pathconvert pathsep="/**/*," refid="source.path" property="my_fileset_pattern">
<filtermapper>
<replacestring from="${basedir}/" to="" />
</filtermapper>
</pathconvert>
That will populate ${my_fileset_pattern} with a string like:
1/**/*,2/**/*,3
if source.path consisted of the three directories 1, 2, and 3 under the basedir. We're using the pathsep to insert wildcards that will expand to the full set of files later.
The property can now be used to generate a fileset of all the files. Note that an extra trailing /**/* is needed to expand out the last directory in the set. Exclusion can be applied at this point.
<fileset dir="." id="my_fileset" includes="${my_fileset_pattern}/**/*">
<exclude name="**/*.java" />
</fileset>
The copy of all the non-java files then becomes:
<copy todir="${classes.dir}" preservelastmodified="true">
<fileset refid="my_fileset" />
</copy>
That will copy the source files over retaining the source directory structure under todir. If needed, the flatten attribute of the copy task can be set to instead make all the source files copy directly to todir.
Note that the pathconvert example here is for a unix fileseystem, rather than windows. If something portable is needed, then the file.separator property should be used to build up the pattern:
<property name="wildcard" value="${file.separator}**${file.separator}*" />
<pathconvert pathsep="${wildcard}," refid="source.path" property="my_fileset">
...
You could use the foreach task from the ant-contrib library:
<target name="build">
...
<!-- copy resources from src to bin -->
<foreach target="copy.resources" param="resource.dir">
<path refid="source.path"/>
</foreach>
</target>
<target name="copy.resources">
<copy todir="${classes.dir}" preservelastmodified="true">
<fileset dir="${resource.dir}" exclude="**/*.java">
</copy>
</target>
If your source.path contains file paths as well then you could the if task (also from ant-contrib) to prevent attempting to copy files for a file path, e.g.
<target name="copy.resources">
<if>
<available file="${classes.dir}" type="dir"/>
<then>
<copy todir="${classes.dir}" preservelastmodified="true">
<fileset dir="${resource.dir}" exclude="**/*.java">
</copy>
</then>
</if>
</target>

Resources