forked from stackb/rules_proto
-
Notifications
You must be signed in to change notification settings - Fork 0
/
protoc-gen-scala.go
102 lines (93 loc) · 2.63 KB
/
protoc-gen-scala.go
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
91
92
93
94
95
96
97
98
99
100
101
102
package main
import (
"log"
"os"
"os/exec"
"path"
"path/filepath"
"syscall"
)
func main() {
// This works due to the expected sandbox layout:
//
// ./bazel-out/host/bin/external/build_stack_rules_proto/scala/compiler_plugin_deploy.jar
// ./bazel-out/host/bin/external/build_stack_rules_proto/scala/linux_amd64_stripped
// ./bazel-out/host/bin/external/build_stack_rules_proto/scala/linux_amd64_stripped/protoc-gen-scala
// listFiles(".")
jar := mustFindInSandbox(path.Dir(os.Args[0]), "compiler_plugin_deploy.jar")
err, exitCode := run("external/local_jdk/jre/bin/java", append([]string{"-jar", jar}, os.Args...), ".", nil)
if err != nil {
log.Printf("%v", err)
}
os.Exit(exitCode)
}
func mustFindInSandbox(dir, file string) string {
attempts := 0
for {
// Just in case we have a bug that will loop forever in some random
// filesystem pattern we haven't thought of
if attempts > 1000 {
log.Fatalf("Too many attempts to find %s within %s", file, dir)
}
if dir == "" {
log.Fatalf("Failed to find %s within %s", file, dir)
}
abs := path.Join(dir, file)
if exists(abs) {
return abs
}
dir = path.Dir(dir)
attempts++
}
}
// exists - return true if a file entry exists
func exists(name string) bool {
if _, err := os.Stat(name); err != nil {
if os.IsNotExist(err) {
return false
}
}
return true
}
// run a command
func run(entrypoint string, args []string, dir string, env []string) (error, int) {
cmd := exec.Command(entrypoint, args...)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Env = env
cmd.Dir = dir
err := cmd.Run()
var exitCode int
if err != nil {
// try to get the exit code
if exitError, ok := err.(*exec.ExitError); ok {
ws := exitError.Sys().(syscall.WaitStatus)
exitCode = ws.ExitStatus()
} else {
// This will happen (in OSX) if `name` is not available in $PATH,
// in this situation, exit code could not be get, and stderr will be
// empty string very likely, so we use the default fail code, and format err
// to string and set to stderr
log.Printf("Could not get exit code for failed program: %v, %v", entrypoint, args)
exitCode = -1
}
} else {
// success, exitCode should be 0 if go is ok
ws := cmd.ProcessState.Sys().(syscall.WaitStatus)
exitCode = ws.ExitStatus()
}
return err, exitCode
}
// listFiles - convenience debugging function to log the files under a given dir
func listFiles(dir string) error {
log.Println("Listing files under " + dir)
return filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if err != nil {
log.Printf("%v\n", err)
return err
}
log.Println(path)
return nil
})
}