Ti Strga
Ti Strga

Reputation: 1389

What are the usage restrictions on Ant's if/unless conditional attributes?

So we're using basic Ant 1.9.4, with a little use of 1.9.1's new if/unless attributes. For example,

<project xmlns:if="ant:if" xmlns:unless="ant:unless">
.... miles and miles of XML ....

<jar ....>
  <service ....>
    <provider classname="a.b.c.X" if:true="${some.flag}"/>
    <provider ..../>
  </service>
  <fileset>
    ....the stuff in here will matter shortly....
  </fileset>
</jar>

with some.flag always set to true or false, never left unset, and never set to any other value (assigned inside a property file read in earlier, if that matters), and it works wonderfully, giving us exactly the behavior we need. Joy!

More recently, we tried to make some of the jar task's fileset entries a little smarter, such as

<fileset dir="somedir">
  <include name="optional_file" if:true="${some.flag}"/>  <!-- same property name as before -->
</fileset>

With this syntax, we get an error "A zip file cannot include itself", with a line number pointing to the start of the jar task. This is obviously bogus syntax. However, changing this second if:true to simply if out of desperation -- and making no other changes -- avoids the error and gives us correct flag-based optional inclusion behavior.

What's going on here? Is the new syntax simply unavailable in <fileset> and/or fileset's nested <include> blocks?

As an experiment, I tried using an if:true or if:set attribute as appropriate in a few other useful places. Some places it worked perfectly. Some places I got some bizarre nonsense error, clearly the kind of thing that a parser prints when it's gone off the rails. Each time, reworking if:set="$(foo}" into if="foo" and if:true="${foo}" into if="${foo}" got back to the desired if-then behavior. So it's not a blocking problem, but we'd rather have the self-documenting :condition if we could.

I couldn't find mention of any such restriction in the Ant manual, but the manual describes the if/unless syntax in at least two different places using different descriptions. (I'm not sure where they are due to the manual's use of HTML frames; every URL shows up as index.html. Anytime I refer to the manual it feels like I'm browsing like it's 1999, baby! *does MC Hammer slide out of the room*)

Upvotes: 1

Views: 377

Answers (1)

Chad Nouis
Chad Nouis

Reputation: 7041

Since Ant 1.4, <include> and <exclude> elements nested under <patternset> elements have supported if and else attributes. Each <fileset> has an implicit <patternset> nested under it, so the if and else attributes are available to it...

<condition property="some.flag.istrue">
  <istrue value="${some.flag}"/>
</condition>
<fileset dir="somedir">
  <!-- The "if" below is different than "if:true". -->
  <include name="optional_file" if="some.flag.istrue"/>
</fileset>

In the above example, the if in <include> is an ordinary Ant attribute in the "default" Ant XML namespace. On the other hand, if:true is in the ant:if XML namespace.

The namespaced if:true doesn't work well with <include> elements. If the value provided to if:true doesn't evaluate to true, then Ant behaves as if the entire <include> element never existed. This is bad because Ant takes empty patternsets to mean "match every file". This is likely why you received the "A zip file cannot include itself" error; the <fileset> was likely containing the destination JAR file.

Stick with the plain if and else attributes for <include> and <exclude> elements and things should work.

Upvotes: 1

Related Questions