aboutsummaryrefslogtreecommitdiff
path: root/buildSrc/src/main/groovy/org/jetbrains/CrossPlatformExec.groovy
blob: a83d6f650d4f8d51b108112d86272277b7fbdbcd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
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(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(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(commandFile, windows);
        };
    }

    private static String resolveCommandFromFile(Path commandFile, boolean windows) {
        if (!Files.isExecutable(commandFile)) {
            return null;
        }

        String resolvedCommand = 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);
    }
}