From 6a6770833f2df4fcb92c9869a6e2605c22d83dee Mon Sep 17 00:00:00 2001 From: Slawomir Jaranowski Date: Wed, 1 May 2024 13:20:50 +0200 Subject: [PATCH] [MINVOKER-335] Preserve symlinks for copied files --- .../invoker.properties | 19 ++++++ .../MINVOKER-335-symlinks-in-source/pom.xml | 65 +++++++++++++++++++ .../setup.groovy | 34 ++++++++++ .../src/it/clone-symlinks/pom.xml | 32 +++++++++ .../verify.groovy | 26 ++++++++ .../plugins/invoker/AbstractInvokerMojo.java | 9 ++- 6 files changed, 183 insertions(+), 2 deletions(-) create mode 100644 src/it/MINVOKER-335-symlinks-in-source/invoker.properties create mode 100644 src/it/MINVOKER-335-symlinks-in-source/pom.xml create mode 100644 src/it/MINVOKER-335-symlinks-in-source/setup.groovy create mode 100644 src/it/MINVOKER-335-symlinks-in-source/src/it/clone-symlinks/pom.xml create mode 100644 src/it/MINVOKER-335-symlinks-in-source/verify.groovy diff --git a/src/it/MINVOKER-335-symlinks-in-source/invoker.properties b/src/it/MINVOKER-335-symlinks-in-source/invoker.properties new file mode 100644 index 00000000..f45dd01a --- /dev/null +++ b/src/it/MINVOKER-335-symlinks-in-source/invoker.properties @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# NOTE: Don't clean here to be able to detect test failures +invoker.goals = initialize diff --git a/src/it/MINVOKER-335-symlinks-in-source/pom.xml b/src/it/MINVOKER-335-symlinks-in-source/pom.xml new file mode 100644 index 00000000..a62be04d --- /dev/null +++ b/src/it/MINVOKER-335-symlinks-in-source/pom.xml @@ -0,0 +1,65 @@ + + + + + + 4.0.0 + + org.apache.maven.plugins.invoker + clone-clean-invocation + 1.0-SNAPSHOT + pom + + Test to check for copping symlinks from source to target + https://issues.apache.org/jira/browse/MINVOKER-335 + + + UTF-8 + + + + + + org.apache.maven.plugins + maven-invoker-plugin + @project.version@ + + ${project.build.directory}/it + + */pom.xml + + + validate + + + + + integration-test + initialize + + run + + + + + + + + diff --git a/src/it/MINVOKER-335-symlinks-in-source/setup.groovy b/src/it/MINVOKER-335-symlinks-in-source/setup.groovy new file mode 100644 index 00000000..1d0e0fbb --- /dev/null +++ b/src/it/MINVOKER-335-symlinks-in-source/setup.groovy @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.nio.file.Files +import java.nio.file.Paths + +def projectPath = new File(basedir, 'src/it/clone-symlinks').toPath() + +def testDir = projectPath.resolve('testDir'); +def testFile = projectPath.resolve('test.txt') + +Files.createDirectory(testDir) +Files.createFile(testFile) + +Files.createSymbolicLink(projectPath.resolve('testDirLink'), Paths.get('testDir')) +Files.createSymbolicLink(projectPath.resolve('testLink.txt'), Paths.get('test.txt')) + +true \ No newline at end of file diff --git a/src/it/MINVOKER-335-symlinks-in-source/src/it/clone-symlinks/pom.xml b/src/it/MINVOKER-335-symlinks-in-source/src/it/clone-symlinks/pom.xml new file mode 100644 index 00000000..b49b4127 --- /dev/null +++ b/src/it/MINVOKER-335-symlinks-in-source/src/it/clone-symlinks/pom.xml @@ -0,0 +1,32 @@ + + + + + + 4.0.0 + test + clone-symlnks + 0.1-SNAPSHOT + pom + + + UTF-8 + + diff --git a/src/it/MINVOKER-335-symlinks-in-source/verify.groovy b/src/it/MINVOKER-335-symlinks-in-source/verify.groovy new file mode 100644 index 00000000..dee7a378 --- /dev/null +++ b/src/it/MINVOKER-335-symlinks-in-source/verify.groovy @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.nio.file.Files +import java.nio.file.Paths + +def projectPath = new File(basedir, 'target/it/clone-symlinks').toPath() + +assert Files.readSymbolicLink(projectPath.resolve('testDirLink')) == Paths.get('testDir') +assert Files.readSymbolicLink(projectPath.resolve('testLink.txt')) == Paths.get('test.txt') diff --git a/src/main/java/org/apache/maven/plugins/invoker/AbstractInvokerMojo.java b/src/main/java/org/apache/maven/plugins/invoker/AbstractInvokerMojo.java index 3f13a13a..70ca4fec 100644 --- a/src/main/java/org/apache/maven/plugins/invoker/AbstractInvokerMojo.java +++ b/src/main/java/org/apache/maven/plugins/invoker/AbstractInvokerMojo.java @@ -92,6 +92,7 @@ import org.codehaus.plexus.util.FileUtils; import org.codehaus.plexus.util.IOUtil; import org.codehaus.plexus.util.InterpolationFilterReader; +import org.codehaus.plexus.util.NioFiles; import org.codehaus.plexus.util.ReflectionUtils; import org.codehaus.plexus.util.cli.CommandLineException; import org.codehaus.plexus.util.cli.CommandLineUtils; @@ -1178,14 +1179,18 @@ private void copyDirectoryStructure(File sourceDir, File destDir) throws IOExcep /* * NOTE: Make sure the destination directory is always there (even if empty) to support POM-less ITs. */ - destDir.mkdirs(); + Files.createDirectories(destDir.toPath()); // Create all the directories, including any symlinks present in source FileUtils.mkDirs(sourceDir, scanner.getIncludedDirectories(), destDir); for (String includedFile : scanner.getIncludedFiles()) { File sourceFile = new File(sourceDir, includedFile); File destFile = new File(destDir, includedFile); - FileUtils.copyFile(sourceFile, destFile); + if (NioFiles.isSymbolicLink(sourceFile)) { + NioFiles.createSymbolicLink(destFile, NioFiles.readSymbolicLink(sourceFile)); + } else { + FileUtils.copyFile(sourceFile, destFile); + } // ensure clone project must be writable for additional changes destFile.setWritable(true);