#27 support else in the if task

closed-postponed
Gert Driesen
Tasks (82)
5
2005-01-23
2004-06-15
Troy Laurin
No

Currently, to create an if/else structure in the build
file requires distinct if and ifnot tasks on the same
condition.

for example (Using 0.84 schema):
<available type="File"
resource="${project.dir}/project.build"
property="project.buildfile-override" />
<if propertytrue="project.buildfile-override">
<property name="project.buildfile"
value="${project.dir}/project.build" />
<echo message="Building project ${name} with override
buildfile" />
</if>
<ifnot propertytrue="project.buildfile-override">
<property name="project.buildfile"
value="default.build" />
<echo message="Building project ${name} with default
buildfile" />
</ifnot>

Moving to the new functional/expression way of
expressing the above, the need for else support becomes
much stronger, to ensure that the conditions remain in
sync. Compare:
<if test="${file::exists(project.dir + '/project.build')}">
<property name="project.buildfile"
value="${project.dir}/project.build" />
<echo message="Building project ${name} with override
buildfile" />
</if>
<ifnot test="${file::exists(project.dir +
'/project.build')}">
<property name="project.buildfile"
value="default.build" />
<echo message="Building project ${name} with default
buildfile" />
</ifnot>

with:
<if test="${file::exists(project.dir + '/project.build')}">
<then>
<property name="project.buildfile"
value="${project.dir}/project.build" />
<echo message="Building project ${name} with
override buildfile" />
</then>
<else>
<property name="project.buildfile"
value="default.build" />
<echo message="Building project ${name} with
default buildfile" />
</else>
</if>

Discussion

  • Troy Laurin
    Troy Laurin
    2004-06-15

    Logged In: YES
    user_id=1062940

    Again, I can attach a patch if requested.

     
  • Troy Laurin
    Troy Laurin
    2004-07-01

    Logged In: YES
    user_id=1062940

    Attached a patch (diff) to IfTask.cs that adds if/then/else
    support to the if task while maintaining backwards
    compatibility.

     
  • Troy Laurin
    Troy Laurin
    2004-07-01

    Tests for the updated IfTask

     
    Attachments
  • Troy Laurin
    Troy Laurin
    2004-07-01

    Logged In: YES
    user_id=1062940

    Attached IfTest.cs diff including new tests for if/then/else
    behaviour of IfTask.

     
  • Troy Laurin
    Troy Laurin
    2004-07-01

    Logged In: YES
    user_id=1062940

    Fixed a few issues in the IfTask diff.
    Diff is based on CVS version 1.34 - latest as of now.

     
  • Troy Laurin
    Troy Laurin
    2004-07-01

    Patch to IfTask to support if/then/else

     
    Attachments
  • Troy Laurin
    Troy Laurin
    2004-07-01

    Logged In: YES
    user_id=1062940

    Third time lucky

     
  • Logged In: YES
    user_id=445334

    Another way to approach this is to do something like this:

    <available type="File"
    resource="${project.dir}/project.build"
    property="project.buildfile-override" />

    <property name="project.buildfile"
    value="${project.dir}/project.build"
    if="${project.buildfile-override}" />

    <property name="build.file" value="default.build"
    unless="${project.buildfile-override}" />

    HTH,
    Felice

     
  • Logged In: YES
    user_id=445334

    Oops ...

    <property name="build.file" value="default.build"
    unless="${project.buildfile-override}" />

    Should be:

    <property name="project.buildfile" value="default.build"
    unless="${project.buildfile-override}" />

     
  • Troy Laurin
    Troy Laurin
    2004-07-24

    Logged In: YES
    user_id=1062940

    Not quite the same thing... note that you haven't included
    the echo statements, so you are required to duplicate your
    if and unless attributes.

    Having said that, another way of implementing this without
    changing the if task is:
    <target name="foo">
    <property name="test.result" value="${perform::test()}" />
    <call target="test-branch" />
    </target>
    <target name="test-branch"
    depends="test-branch.true,test-branch.false" />
    <target name="test-branch.true" if="${test.result}">
    <if-true-tasks />
    </target>
    <target name="test-branch.false" unless="${test.result}">
    <else-tasks />
    </target>

    I'd still charge that the above isn't as succinct as the
    equivalent with if-else:
    <target name="foo">
    <if test="${perform::test()}">
    <do>
    <if-true-tasks />
    </do>
    <else>
    <else-tasks />
    </else>
    </if>
    </target>

    The if-else variant has the added advantages of not
    cluttering the target and property namespaces, and there's
    no chance of introducing errors by renaming the
    test-property in only a few locations. Also, the foo target
    using if-else can be used recursively, which might break the
    property method... I don't know how much of a good thing
    this last is, though ;-)

    -- Troy

     
  • Troy Laurin
    Troy Laurin
    2004-07-29

    Logged In: YES
    user_id=1062940

    Upon reflection, where the build is going to perform a chain
    of comparisons, the most concise/expressive option in the
    buildfile is something akin to a switch expression: (Pardon
    the contrived example)

    <if test="${foo = 'debug'}">
    <echo message="Debug!" />
    </if>
    <if test='${foo <> 'debug' and optimise <> 'false'}">
    <property name="foo" value="release" />
    <echo message="Release!" />
    </if>
    <if test='${foo <> 'debug' and optimise = 'false'}">
    <fail message="Not debug or release?" />
    </if>

    equivalent in case:
    <switch>
    <case test="${foo = 'debug'}">
    <echo message="Debug!" />
    </case>
    <case test='${optimise <> 'false'}">
    <property name="foo" value="release" />
    <echo message="Release!" />
    </case>
    <default>
    <fail message="Not debug or release?" />
    </default>
    </switch>

    Note that the switch expression is intended above as an
    extended if-else expression, so only the first case element
    that tests true will be executed.

    Comments on the above are welcome... I'm not convinced that
    a well-designed build file should use the above, but having
    it available might make less-well-designed build files a
    little easier to follow :-)

     
  • Gert Driesen
    Gert Driesen
    2005-01-23

    Logged In: YES
    user_id=707851

    We'll probably add a <choice> task, similar to the <choice>
    construct in XSLT.

     
  • Gert Driesen
    Gert Driesen
    2005-01-23

    • labels: --> Tasks
    • assigned_to: nobody --> drieseng
    • status: open --> closed-postponed