1

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>
why_vincent
  • 2,172
  • 9
  • 33
  • 49

1 Answers1

4

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"...].

Community
  • 1
  • 1
Dante WWWW
  • 2,729
  • 1
  • 17
  • 33
  • The target test was to have the name doStuff, my bad. I think seems like a good idea, and the script works, but I cannot understand why it is so hard to increment an int like this. I find it rather common to want a target that does the same thing several times and store each loop-cycle in a unique filename. Sure, tstamp is ordered, but rather inconvenient compared to an int. – why_vincent May 22 '14 at 10:42
  • In an Ant script, when there's a need to "do the same thing several times," a good rule of thumb is to prefer a `` over a ``. Ant-Contrib's `` task works well with `` tasks. – Chad Nouis May 22 '14 at 13:23
  • @ChadNouis Yes, although here the key is to increment an integer. Maybe using `` together with `` could lead to a solution that doesn't need any beanshell. – Dante WWWW May 22 '14 at 13:54
  • 1
    IMO this solution goes in the right direction, but is suboptimal because of using antcall which opens a new projectscope for every call and should be avoided - using macrodef is much better as Chad Nouis already mentioned. Also using builtin javascript engine is better as beanshell because beanshell needs additional jars (bsf.jar and bsh.jar => latest release bsh-2.0b4 from 2005 !). – Rebse May 22 '14 at 17:00
  • @Rebse I just don't know how to write JS :P Actually the question can be divided into two parts. For the first part, the op wants a unique filename. No matter what kind of loop he want to use, `` should be a better choice than increment int. For the second part, the op has to execute something multiple times. Here I agree with @ChadNouis's comment. – Dante WWWW May 23 '14 at 02:48