diff options
Diffstat (limited to 'buildSrc')
-rw-r--r-- | buildSrc/src/main/groovy/org/jetbrains/CrossPlatformExec.groovy | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/buildSrc/src/main/groovy/org/jetbrains/CrossPlatformExec.groovy b/buildSrc/src/main/groovy/org/jetbrains/CrossPlatformExec.groovy new file mode 100644 index 00000000..9c6780f7 --- /dev/null +++ b/buildSrc/src/main/groovy/org/jetbrains/CrossPlatformExec.groovy @@ -0,0 +1,92 @@ +package org.jetbrains + +import org.gradle.api.tasks.AbstractExecTask +import org.gradle.api.tasks.TaskAction +import org.gradle.internal.os.OperatingSystem + +import java.nio.file.Files +import java.nio.file.Path +import java.nio.file.Paths + +class CrossPlatformExec extends AbstractExecTask { + private static final def windowsExtensions = ['bat', 'cmd', 'exe']; + private static final def unixExtensions = [null, 'sh']; + + private boolean windows; + + public CrossPlatformExec() { + super(CrossPlatformExec.class); + windows = OperatingSystem.current().windows; + } + + @Override + @TaskAction + protected void exec() { + List<String> commandLine = this.getCommandLine(); + + if (!commandLine.isEmpty()) { + commandLine[0] = findCommand(workingDir, commandLine[0], windows); + } + + if (windows) { + if (!commandLine.isEmpty() && commandLine[0]) { + commandLine + } + commandLine.add(0, '/c'); + commandLine.add(0, 'cmd'); + } + + this.setCommandLine(commandLine); + + super.exec(); + } + + private static String findCommand(File workingDir, String command, boolean windows) { + command = normalizeCommandPaths(command); + def extensions = windows ? windowsExtensions : unixExtensions; + + return extensions.findResult(command) { extension -> + Path commandFile + if (extension) { + commandFile = Paths.get(command + '.' + extension); + } else { + commandFile = Paths.get(command); + } + + return resolveCommandFromFile(workingDir, commandFile, windows); + }; + } + + private static String resolveCommandFromFile(File workingDir, Path commandFile, boolean windows) { + if (!Files.isExecutable(commandFile)) { + return null; + } + + Path cwd = Paths.get(workingDir.absolutePath).toAbsolutePath().normalize(); + + String resolvedCommand = cwd.relativize(commandFile.toAbsolutePath().normalize()); + + if (!windows && !resolvedCommand.startsWith('.')) { + resolvedCommand = '.' + File.separator + resolvedCommand; + } + + return resolvedCommand; + } + + private static String normalizeCommandPaths(String command) { + // need to escape backslash so it works with regex + String backslashSeparator = '\\\\'; + + String forwardSlashSeparator = '/'; + + // escape separator if it's a backslash + char backslash = '\\'; + String separator = File.separatorChar == backslash ? backslashSeparator : File.separator + + return command + // first replace all of the backslashes with forward slashes + .replaceAll(backslashSeparator, forwardSlashSeparator) + // then replace all forward slashes with whatever the separator actually is + .replaceAll(forwardSlashSeparator, separator); + } +}
\ No newline at end of file |