Search code examples
propertiesnantexpansionfileset

Fileset/patternset's refid attribute isn't expanded. How would you write a target that operates on an arbitrary set of files?


I have a set of targets that each do essentially the same thing except each contains a specific patternset on which to perform its tasks. I want to collapse these targets into a single "reusable" target that instead takes a set of files "as a parameter".

For example, this

<target name="echo1">
  <foreach item="File" property="fn">
    <in>
      <items>
        <include name="*.config"/>
      </items>
    </in>
    <do>
      <echo message="${fn}" />
    </do>
  </foreach>
</target>

<target name="echo2">
  <foreach item="File" property="fn">
    <in>
      <items>
        <include name="*.xml"/>
      </items>
    </in>
    <do>
      <echo message="${fn}" />
    </do>
  </foreach>
</target>

<target name="use">
  <call target="echo1"/>
  <call target="echo2"/>
</target>

would be replaced by

<patternset id="configs">
   <include name="*.config"/>
</patternset>

<patternset id="xmls">
   <include name="*.xml"/>
</patternset>

<target name="echo">
  <foreach item="File" property="fn">
    <in>
      <items>
        <patternset refid="${sourcefiles}"/>
      </items>
    </in>
    <do>
      <echo message="${fn}" />
    </do>
  </foreach>
</target>

<target name="use">
  <property name="sourcefiles" value="configs"/>
  <call target="echo"/>
  <property name="sourcefiles" value="xmls"/>
  <call target="echo"/>
</target>

However, it turns out that refid is not expanded as answered in a nant-dev email posting because patternsets and filesets differ from properties. In this non-working code, when echo is called, its patternset element references a patternset literally named ${sourcefiles} instead of the one named test.

How would one write a re-usable NAnt target that operates on a varying set of files? Is there a way to do this in NAnt as-is without resorting to writing custom tasks?


Solution

  • I finally came up with this, which serves my purposes. As a bonus, this also demonstrates calling a target dynamically.

    <project
      name="dynamic-fileset"
      default="use"
      xmlns="http://nant.sourceforge.net/release/0.86-beta1/nant.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    
        <target name="configs">
            <fileset id="files">
               <include name="*.config"/>
            </fileset>
        </target>
    
        <target name="xmls">
            <fileset id="files">
               <include name="*.xml"/>
            </fileset>
        </target>
    
        <target name="echo">
          <foreach item="File" property="fn">
            <in>
              <items refid="files"/>
            </in>
            <do>
              <echo message="${fn}" />
            </do>
          </foreach>
        </target>
    
        <target name="use">
          <property name="grouplist" value="xmls,configs"/>
          <foreach item="String" in="${grouplist}" delim="," property="filegroup">
            <do>
              <call target="${filegroup}"/>
              <call target="echo"/>
            </do>
          </foreach>        
        </target>
    </project>