| 
					
				 | 
			
			
				@@ -1,9 +1,12 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 package main 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  "bytes" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   "flag" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   "fmt" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  "io/ioutil" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   "os" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  "os/exec" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   "path" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   "runtime" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   "strings" 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -23,16 +26,16 @@ var SHLIB_EXT = map[string]string { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 func main() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  var outputPath, name, varname, _flag, pkg string 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  var printVersion bool 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  var outputDir, name, varname, _flag, pkg string 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  var printVersion, disableMakefile bool 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   flag.StringVar(&name, "n", "", "Name of the plugin, CamelCase. Required.") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  flag.StringVar(&outputPath, "o", "", "Output path of the generated plugin code. If not " + 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      "specified, inferred from -n.") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  flag.StringVar(&outputDir, "o", ".", "Output directory for the generated plugin files.") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   flag.StringVar(&varname, "varname", "", "Name of the plugin instance variable, If not " + 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       "specified, inferred from -n.") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   flag.StringVar(&_flag, "flag", "", "Name of the plugin activation cmdline flag, If not " + 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       "specified, inferred from -varname.") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   flag.BoolVar(&printVersion, "version", false, "Print version information and exit.") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  flag.BoolVar(&disableMakefile, "no-makefile", false, "Do not generate the Makefile.") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   flag.StringVar(&pkg, "package", "main", "Name of the package.") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   flag.Parse() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if printVersion { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -45,11 +48,11 @@ func main() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     os.Exit(1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   splitted := camelcase.Split(name) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if outputPath == "" { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    outputPath = strings.ToLower(strings.Join(splitted, "_")) + ".go" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } else if !strings.HasSuffix(outputPath, ".go") { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    panic("-o must end with \".go\"") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  err := os.MkdirAll(outputDir, os.ModePerm) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if err != nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    panic(err) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  outputPath := path.Join(outputDir, strings.ToLower(strings.Join(splitted, "_")) + ".go") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   gen := template.Must(template.New("plugin").Parse(PLUGIN_TEMPLATE_SOURCE)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   outFile, err := os.Create(outputPath) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if err != nil { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -60,15 +63,66 @@ func main() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     varname = strings.ToLower(splitted[0]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if _flag == "" { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    _flag = strings.Join(splitted, "-") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    _flag = strings.ToLower(strings.Join(splitted, "-")) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   outputBase := path.Base(outputPath) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   shlib := outputBase[:len(outputBase)-2] + SHLIB_EXT[runtime.GOOS] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  protoBuf := outputPath[:len(outputPath)-3] + ".proto" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  pbGo := outputPath[:len(outputPath)-3] + ".pb.go" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   dict := map[string]string{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     "name": name, "varname": varname, "flag": _flag, "package": pkg, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    "output": outputPath, "shlib": shlib} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    "output": outputPath, "shlib": shlib, "proto": protoBuf, "protogo": pbGo, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    "outdir": outputDir} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   err = gen.Execute(outFile, dict) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if err != nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     panic(err) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // write pb file 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  ioutil.WriteFile(protoBuf, []byte(fmt.Sprintf(`syntax = "proto3"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+option go_package = "%s"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+message %sResultMessage { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // add fields here 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // reference: https://developers.google.com/protocol-buffers/docs/proto3 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // example: pb/pb.proto https://github.com/src-d/hercules/blob/master/pb/pb.proto 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}`, pkg, name)), 0666) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // generate the pb Go file 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  protoc, err := exec.LookPath("protoc") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  args := [...]string{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    protoc, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    "--gogo_out=" + outputDir, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    "--proto_path=" + outputDir, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    protoBuf, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  env := os.Environ() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  env = append(env, fmt.Sprintf( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    "PATH=%s:%s", os.Getenv("PATH"), path.Join(os.Getenv("GOPATH"), "bin"))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if err != nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    panic("protoc was not found at " + env[len(env)-1]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  cmd := exec.Cmd{Path: protoc, Args: args[:], Env: env, Stdout: os.Stdout, Stderr: os.Stderr} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  err = cmd.Run() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if err != nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    panic(err) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if !disableMakefile { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    makefile := path.Join(outputDir, "Makefile") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    gen = template.Must(template.New("plugin").Parse(`all: {{.shlib}} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{{.shlib}}: {{.output}} {{.protogo}} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+` + "\t" + `go build -buildmode=plugin {{.output}} {{.protogo}} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{{.protogo}}: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+` + "\t" + `PATH=$PATH:$GOPATH/bin protoc --gogo_out=. --proto_path=. {{.proto}} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+`)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    buffer := new(bytes.Buffer) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    mkrelative := func(name string) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      dict[name] = path.Base(dict[name]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    mkrelative("output") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    mkrelative("protogo") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    mkrelative("proto") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    gen.Execute(buffer, dict) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ioutil.WriteFile(makefile, buffer.Bytes(), 0666) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 |