1
votes

I need some help with ant. I have a target where I loop over a fileset using foreach from ant-contrib. I call another target(lets call it doStuff) for each of iteration of the loop.

The output of doStuff is something that I would like to store in a file. I would like the files to have unique names and I thought that an integer that gets incremented with every loop would suit me well.

I tried many variations of the code below and had no success. I have probably not understod and yet. It seems to work with immutable properties, making the targets stateless. While I do enjoy that, it doesn't help me with my current problem.

Is there any way to set the myInt in the first target and keep the 'state', increment it with every loop and pass it on to the next target?

<var name="myInt"  unset="true"/>

<var name="myInt" value="0"/>

<target name="default">
    <foreach target="doStuff" param="theFile">
        <fileset dir="" casesensitive="yes">
            <depth max="0"/>
        </fileset>
    </foreach>
</target>

<target name="doStuff"  description="Make output directories and run the MXUnit task">
    <var name="op1" value="${myInt}"/>
    <var name="op2" value="1"/>
    <var name="op" value="+"/>
    <math result="result" operand1="${op1}" operation="${op}" operand2="${op2}" datatype="int"/>
    <var name="myInt" unset="true"/>
    <var name="myInt" value="${result}"/>  
<!-- Here I save the file with the name ${result}-->
</target>
1
How do your two targets (default and test) relate? Could you specify your example better and make it runnable?Pavel S.
My mistake, the target test had the wrong name. Updated it now.why_vincent

1 Answers

4
votes

First of all, a suggestion: consider if it is really necessary to use a self-increment integer -- if you just want a unique, sortable filename, you can use <tstamp> instead.


And this part should be considered as a bad practice to use Ant.

From your description I don't see how your "test" target is called. So I will assume that you just want your "doStuff" to use a self-increment integer each time when it's called.

You can try <script> (example code below is not tested):

<target name="default">
    <script language="beanshell" classpathref="your-classpath-ref-id">
        String[] theFiles = getProject().getProperty("theFile").split(",");

        for (int i = 1; i &lt;= theFiles.length; i++) {
            CallTarget antcall = new CallTarget(); // the class of antcall task
            antcall.setTarget("doStuff");
            Property param1 = antcall.createParam();
            param1.setName("number");
            param1.setValue(String.valueOf(i));
            ... // maybe param2 to pass theFiles[i] to doStuff?
            antcall.execute();
        }
    </script>
</target>

If the dependency library of beanshell is not in your Ant's default classpath, you need to include the jar in your classpath with the id "your-classpath-ref-id".


Update

Please read David W's answer to this question: Ant - How can I run the same depends from multiple targets. This answer gives a good point about what Ant really is -- not a programming language, but a Matrix Dependency Language.

Using a self-increment int with a loop is a feature of a fully featured programming language. If you do want it, you can develop a library like Ant-contrib to provide such a feature. However, I still prefer time stamp over integer. When you processes the filenames as strings, time stamps can be sorted properly without any additional effort, while ints will lead to a result like ["1","10","2","3","4"...].