4

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?

Garret Wilson
  • 18,219
  • 30
  • 144
  • 272
  • I would let do the maven-assembly-plugin do the that work... – khmarbaise Aug 04 '22 at 17:49
  • Your `pom.xml` looks quite complex. I'm not 100% convinced the `maven-antrun-plugin` does not move the file. Have you tried to extract only `maven-antrun-plugin` and your shell file to validate it's the antrun plugin and not something else. – asbachb Aug 04 '22 at 18:50
  • @asbachb, as I just added to the question, if you're "not 100% convinced" this is happening you can download the [Guise Mummy 0.1.0](https://github.com/globalmentor/guise/releases/tag/v0.1.0) project and see for yourself that `cli/target/bin/guise.sh` is not being deleted. If I've made a mistake in Maven/AntRun, I'd love to know it! – Garret Wilson Aug 05 '22 at 15:12
  • I don't say it does not happen. I just wanted to ensure that this could be reproduced with a plain project with just the `maven-antrun-plugin` configured. – asbachb Aug 05 '22 at 19:09
  • Did you try to run maven with -X in order to view if there is some other plugin that do the copy after move? I saw that in the list of plugin there is the assembly plugin, did you check assembly file? – Lety Aug 13 '22 at 12:06
  • You could use verbose attribute on move to log the files that are being moved. It could help to debug. – Lety Aug 13 '22 at 12:29
  • Reading pom in your project I did not found any error. So take a look to the ant move source code and I see that it is used sourceFile.renameTo(destFile) that is platform dependent, did you build on windows? Did you use some symbolic link in your filesystem? – Lety Aug 13 '22 at 17:22

2 Answers2

2

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.

Garret Wilson
  • 18,219
  • 30
  • 144
  • 272
-1

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>
djmonki
  • 3,020
  • 7
  • 18
  • The AntRun scripts themselves copy the original file being moved/renamed, so why would it be read-only? In addition I pointed out that adding a subsequent `` works, so why doesn't the `` delete the original file when the `` does? Finally `force` has to do with problems overwriting the _destination_ file, not deleting the original file. (And in this case there is no pre-existing destination file anyway.) – Garret Wilson Aug 07 '22 at 01:51