3

I have a very similar situation as in the the outofdate example (see gengrammer, http://ant-contrib.sourceforge.net/tasks/tasks/outofdate.html): I have a folder with *.class and *.seq files that should be converted to *.pdf with the help of plantuml (a java program).

This is my current task:

<property name="diagram.path" value="../graphics/plantuml/src"/>

...

<target name="diagram-files" depends="update-classpath">
    <outofdate property="manual.outofdate" outputsources="diagram.sources">
        <sourcefiles>
            <fileset dir="${diagram.path}" includes="*.class"/>
            <fileset dir="${diagram.path}" includes="*.seq"/>
        </sourcefiles>
        <mapper type="glob" dir="${diagram.path}" from="*.class" to="graphics/*.pdf"/>
        <mapper type="glob" dir="${diagram.path}" from="*.seq" to="graphics/*.pdf"/>
        <sequential>
            <shellscript shell="bash">
                cd ${diagram.path}
                echo ${diagram.sources}
                #for diagram in ${diagram.sources}
                #do
                # java -jar plantuml ... $diagram
                #done
            </shellscript>
        </sequential>
    </outofdate>
</target>

I can't get this to run because inside ${diagram.sources} all (back)slashes were stripped off. So echoing this variable gives me something like this:

C:UsersMYUSERpath-to-folderANDsoONmyfile.class
C:UsersMYUSERpath-to-folderANDsoONmyfile2.class

Don't know if I made something wrong or this is a feature. Any help would be great!

btw. I'm on Windows 10, but ant is running inside a cygwin shell. I never had problems with this combination.

Chris Nauroth
  • 9,614
  • 1
  • 35
  • 39
aronadaal
  • 9,083
  • 1
  • 19
  • 33

1 Answers1

1

It's unclear if the backslashes were stripped by the Ant outofdate task before execution reached your bash script, or if the backslashes made it into the script and you're seeing the effects of shell escaping.

If it's the latter, then you may be able to solve the problem by wrapping ${diagram.sources} in quotes, so that the shell interprets it as a string literal without escaping. For example:

build.xml

<project>
    <taskdef resource="net/sf/antcontrib/antcontrib.properties">
        <classpath>
            <pathelement location="/Users/naurc001/ant-contrib-0.6-bin/lib/ant-contrib-0.6.jar"/>
        </classpath>
    </taskdef>
    <property name="diagram.path" value="../graphics/plantuml/src"/>
    <property name="diagram.sources.property" value="C:\private\tmp\anttest\graphics\plantuml\src\myfile.class C:\private\tmp\anttest\graphics\plantuml\src\myfile2.class" />
    <target name="diagram-files">
        <outofdate property="manual.outofdate" outputsources="diagram.sources">
            <sourcefiles>
                <fileset dir="${diagram.path}" includes="*.class"/>
                <fileset dir="${diagram.path}" includes="*.seq"/>
            </sourcefiles>
            <mapper type="glob" dir="${diagram.path}" from="*.class" to="graphics/*.pdf"/>
            <mapper type="glob" dir="${diagram.path}" from="*.seq" to="graphics/*.pdf"/>
            <sequential>
                <shellscript shell="bash">
                    echo Unquoted: ${diagram.sources.property}
                    echo Quoted: '${diagram.sources.property}'
                    for diagram in $(echo '${diagram.sources.property}')
                    do
                        # I don't have plantuml, so just stubbing it to print the command.
                        echo java -jar plantuml ... $diagram
                    done
                </shellscript>
            </sequential>
        </outofdate>
    </target>
</project>

Output

> ant diagram-files
Buildfile: /private/tmp/anttest/proj/build.xml

diagram-files:
[shellscript] Unquoted: 
C:privatetmpanttestgraphicsplantumlsrcmyfile.class 
C:privatetmpanttestgraphicsplantumlsrcmyfile2.class
[shellscript] Quoted: 
C:\private\tmp\anttest\graphics\plantuml\src\myfile.class 
C:\private\tmp\anttest\graphics\plantuml\src\myfile2.class
[shellscript] java -jar plantuml ... 
/private/tmp/anttest/graphics/plantuml/src/myfile.class
[shellscript] java -jar plantuml ... 
/private/tmp/anttest/graphics/plantuml/src/myfile2.class

BUILD SUCCESSFUL
Total time: 0 seconds

Explanation

I don't have access to a Windows machine for direct testing on that platform, so I have simulated the problem by hard-coding my diagram.sources.property to use Windows-style backslashes in the paths. The <shellscript> echoes the same property twice: once without single quotes and once with single quotes. For the unquoted form, the output looks like what you described due to shell escaping. After quoting it, we get the expected results.

However, if we just passed '{diagram.sources.property}' on to other commands like jar ..., then we'd have an unintended side effect. Bash would pass the entire list as a single argument. To fix that, we can wrap the whole thing in $(echo ...) to turn it back into multiple arguments. The test output proves that we invoke the jar command once for each file.

Depending on which tools you need to run, sometimes there is a need to convert Windows-style backslash path separators to Unix-style forward slashes. If that need arises, then I recommend using the cygpath utility inside the bash script to convert backslashes to slashes. In particular, the -u and -w options are helpful here.

The -u and -w options indicate whether you want a conversion to UNIX (POSIX) format (-u) or to Windows format (-w). Use the -d to get DOS-style (8.3) file and path names. The -m option will output Windows-style format but with forward slashes instead of backslashes. This option is especially useful in shell scripts, which use backslashes as an escape character.

You mentioned that you are using Cygwin, but perhaps you also have teammates running on a Mac or straight Linux and you need to interop with them. If so, then you can guard the calls to cygpath inside a check against the value of uname -a. In a Cygwin shell, the output of uname -a will contain some form of "Cygwin".

Additional references on bash escaping:

Chris Nauroth
  • 9,614
  • 1
  • 35
  • 39
  • Thx Chris. I tried both with the same result. So it seems to me that the slashes get stripped inside ant. Do you have any further idea? – aronadaal Jul 24 '17 at 08:57
  • Ok, I put a `` inside the `sequential` tags and the result is correct. I get a list with absolute paths together with slashes. – aronadaal Jul 24 '17 at 10:09
  • Have you tried quoting arguments before passing into the script? E.g. `echo \foo\bar` = `foobar`, but `echo '\foo\bar'` = `\foo\bar`. – Chris Nauroth Jul 24 '17 at 16:04
  • What do you mean by quoting? The paths are getting calculated based on the `filesets` defined inside `sourcefiles`. And they seam to be correct. Echoing them with `` works perfectly but I can't use them inside the shell script. Maybe I have to convert the `${diagram.sources}` from one `\` to `\\`. But this is something ant (-contrib) should do for me... my 2 cents. – aronadaal Jul 25 '17 at 06:53
  • 1
    I have updated the answer to provide more information about what I meant by 'quoting'. I hope this helps. – Chris Nauroth Jul 25 '17 at 15:48
  • Sorry, I'm now back from vacation. I tested your updated answer and it works very well! Thank you! – aronadaal Aug 25 '17 at 15:01