Maven antrun move not deleting source file

Viewed 83

Developing on Windows 10 I have a Java project in Maven that has a Linux "launcher" shell script for the FooBar utility stored in the repository at src/bin/foobar.sh. It uses resource filtering to substitute in the correct executable JAR path so that what gets built is a foobar.sh script that launches the executable JAR in the same directory.

The POM uses org.apache.maven.plugins:maven-antrun-plugin:1.8 to enable the executable flag on the foobar.sh script in the target/bin directory (which has been already been copied using Maven resource filtering, with that directory path stored in the ${binOutputDirectory} property):

<chmod dir="${binOutputDirectory}" includes="**/*.sh" perm="+x" />

Then it renames the foobar.sh file to simply foobar (i.e. it removes the extension) to follow best practices for shell scripts:

<move todir="${binOutputDirectory}">
  <fileset dir="${binOutputDirectory}">
    <include name="**/*.sh" />
  </fileset>
  <mapper type="glob" from="*.sh" to="*" />
</move>

You can see e.g. globalmentor-root pom.xml at c31ae410143f86ebf2bf10467214214d87b2eb61 for the full POM source code. Actual child POMs will simply enable the AntRun operations by providing their executions an appropriate phase like this:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-antrun-plugin</artifactId>
  <executions>
    <execution>
      <id>set-shell-scripts-executable</id>
      <phase>process-resources</phase>
    </execution>
    <execution>
      <id>remove-shell-script-extensions</id>
      <phase>process-resources</phase>
    </execution>
  </executions>
</plugin>

The essential part of that is working fine, and I wind up with a foobar file in my distributable ZIP file, with its executable flag enabled as desired. Unfortunately I also wind up with the original foobar.sh file as well, and I can see in target/bin (where the .sh extension gets removed) that both files are there as well. So it would appear that AntRun <move> is behaving as <copy>.

To see this in action, build the Guise Mummy 0.1.0 project and look in the cli/target/bin directory; you'll see that guise.sh has not been deleted.

To work around the problem, I can add an extraneous <delete> command; this will successfully remove foobar.sh. (The difference in <fileset> syntax is irrelevant; I switched only because it was more concise.)

<move todir="${binOutputDirectory}">
  <fileset dir="${binOutputDirectory}" includes="**/*.sh"/>
  <mapper type="glob" from="*.sh" to="*" />
</move>
<delete>
  <fileset dir="${binOutputDirectory}" includes="**/*.sh"/>
</delete>

Why is AntRun <move> by itself not removing the original target/bin/foobar.sh file after it copies it to target/bin/foobar as part of the move operation?

2 Answers

Upgrading to org.apache.maven.plugins:maven-antrun-plugin:3.1.0 seems to have fixed the problem. When I created this question I had been using v1.8. I can only suppose that org.apache.maven.plugins:maven-antrun-plugin:1.8 is buggy.

Noticed in the pom, within the antrun goals, you are modifying permissions of the .sh script. This does not confirm if the shell script is writeable, it may be read-only:

<execution>
  <id>set-shell-scripts-executable</id>
  <!--
  Enable execute permission for the shell scripts in `${binOutputDirectory}`.
  Enable by specifying a phase (e.g. `process-resources`) in child POM.
  -->
  <phase>none</phase>
  <goals>
    <goal>run</goal>
  </goals>
  <configuration>
    <target>
      <chmod dir="${binOutputDirectory}" includes="**/*.sh" perm="+x" />
    </target>
  </configuration>
</execution>

Try the following, apply the overwrite attribute, like so:

(overwrite overwrite existing files even if the destination files are newer)

<move todir="${binOutputDirectory}" overwrite="true">
  <fileset dir="${binOutputDirectory}">
    <include name="**/*.sh" />
  </fileset>
  <mapper type="glob" from="*.sh" to="*" />
</move>

If that does not work, also add the force attribute, like so:

(force Overwrite read-only destination files)

<move todir="${binOutputDirectory}" overwrite="true" force="true">
  <fileset dir="${binOutputDirectory}">
    <include name="**/*.sh" />
  </fileset>
  <mapper type="glob" from="*.sh" to="*" />
</move>
Related