tags:

views:

343

answers:

1

I have a set of files that I am picking up in an ant build, which I want to split into equal sized sub sets.

What is a good simple way to do this in Ant without adding custom tasks.

Example:

Fileset contains

TestOne.java
TestTwo.java
TestThree.java
TestFour.java
TestFive.java
TestSix.java

I would like 3 filesets

Fileset1

TestOne.java
TestTwo.java

Fileset2

TestThree.java
TestFour.java

Fileset3

TestFive.java
TestSix.java
+2  A: 

Assuming that the order of the files is not important, and when you say no custom tasks you're not excluding the ant script task, something derived from this might be suitable.

<fileset id="Fileset" dir="${basedir}" includes="Test*.java" />

<target name="scr">
    <script language="javascript">
    <![CDATA[
        // Obtain a reference to fileset in the enclosing project
        var fileSet = project.getReference( "Fileset" );

        // Now get matching files.
        var ds = fileSet.getDirectoryScanner( project );
        var includes = ds.getIncludedFiles( );

        var batchSize = 2;
        var batch = 1;
        for ( var i = 0; i < includes.length; i += batchSize )
        {
            // Create a new fileset to hold the sub-Fileset.
            var filesetN = project.createDataType( "fileset" );
            filesetN.setDir( fileSet.getDir( ) );

            // Give the new Fileset an id and associate with the project.
            project.addReference( "Fileset" + batch, filesetN );

            // Populate the sub-Fileset.
            for ( var j = 0; j < batchSize && ( i + j ) < includes.length; j++ )
            {
                filesetN.setIncludes( includes[i + j] );
            }

            batch++;
        }
    ]]>
    </script>

    // Just to illustrate.
    <echo message="Set 1: ${toString:Fileset1}" />
    <echo message="Set 2: ${toString:Fileset2}" />
    <echo message="Set 3: ${toString:Fileset3}" />
</target>

Given the six files you quote, the above gives:

scr:
     [echo] Set 1: TestFive.java;TestFour.java
     [echo] Set 2: TestOne.java;TestSix.java
     [echo] Set 3: TestThree.java;TestTwo.java

I haven't come up with a pure ant way to achieve this. You might consider ant-contrib which is a fairly widely-used set of extensions that caters for looping and mutable properties.

Final comment, for your example set you can get the desired effect, but it won't extend beyond three Filesets. Uses the first and last resource collections.

<target name="reso">
    <first id="Fileset1" count="2">
        <fileset refid="Fileset" />
    </first>
    <last id="Fileset3" count="2">
        <fileset refid="Fileset" />
    </last>
    <difference id="Fileset2">
        <resources refid="Fileset" />
        <resources refid="Fileset1" />
        <resources refid="Fileset3" />
    </difference>
</target>
martin clayton
I was trying to avoid the javascript, but I guess there is no way?
John Sonmez
@John Can't think of a pure ant solution. Have added a couple of other ideas.
martin clayton