• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1package org.jetbrains
2
3import org.gradle.api.tasks.AbstractExecTask
4import org.gradle.api.tasks.TaskAction
5import org.gradle.internal.os.OperatingSystem
6
7import java.nio.file.Files
8import java.nio.file.Path
9import java.nio.file.Paths
10
11class CrossPlatformExec extends AbstractExecTask {
12    private static final def windowsExtensions = ['bat', 'cmd', 'exe'];
13    private static final def unixExtensions = [null, 'sh'];
14
15    private boolean windows;
16
17    public CrossPlatformExec() {
18        super(CrossPlatformExec.class);
19        windows = OperatingSystem.current().windows;
20    }
21
22    @Override
23    @TaskAction
24    protected void exec() {
25        List<String> commandLine = this.getCommandLine();
26
27        if (!commandLine.isEmpty()) {
28            commandLine[0] = findCommand(commandLine[0], windows);
29        }
30
31        if (windows) {
32            if (!commandLine.isEmpty() && commandLine[0]) {
33                commandLine
34            }
35            commandLine.add(0, '/c');
36            commandLine.add(0, 'cmd');
37        }
38
39        this.setCommandLine(commandLine);
40
41        super.exec();
42    }
43
44    private static String findCommand(String command, boolean windows) {
45        command = normalizeCommandPaths(command);
46        def extensions = windows ? windowsExtensions : unixExtensions;
47
48        return extensions.findResult(command) { extension ->
49            Path commandFile
50            if (extension) {
51                commandFile = Paths.get(command + '.' + extension);
52            } else {
53                commandFile = Paths.get(command);
54            }
55
56            return resolveCommandFromFile(commandFile, windows);
57        };
58    }
59
60    private static String resolveCommandFromFile(Path commandFile, boolean windows) {
61        if (!Files.isExecutable(commandFile)) {
62            return null;
63        }
64
65        return commandFile.toAbsolutePath().normalize();
66    }
67
68    private static String normalizeCommandPaths(String command) {
69        // need to escape backslash so it works with regex
70        String backslashSeparator = '\\\\';
71
72        String forwardSlashSeparator = '/';
73
74        // escape separator if it's a backslash
75        char backslash = '\\';
76        String separator = File.separatorChar == backslash ? backslashSeparator : File.separator
77
78        return command
79        // first replace all of the backslashes with forward slashes
80                .replaceAll(backslashSeparator, forwardSlashSeparator)
81        // then replace all forward slashes with whatever the separator actually is
82                .replaceAll(forwardSlashSeparator, separator);
83    }
84}