github.com/gogo/protobuf@v1.3.2/protoc-gen-combo/combo.go (about) 1 // Protocol Buffers for Go with Gadgets 2 // 3 // Copyright (c) 2013, The GoGo Authors. All rights reserved. 4 // http://github.com/gogo/protobuf 5 // 6 // Redistribution and use in source and binary forms, with or without 7 // modification, are permitted provided that the following conditions are 8 // met: 9 // 10 // * Redistributions of source code must retain the above copyright 11 // notice, this list of conditions and the following disclaimer. 12 // * Redistributions in binary form must reproduce the above 13 // copyright notice, this list of conditions and the following disclaimer 14 // in the documentation and/or other materials provided with the 15 // distribution. 16 // 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29 package main 30 31 import ( 32 "bufio" 33 "bytes" 34 "flag" 35 "fmt" 36 "io/ioutil" 37 "os" 38 "os/exec" 39 "path/filepath" 40 "strings" 41 42 "github.com/gogo/protobuf/version" 43 ) 44 45 type MixMatch struct { 46 Old []string 47 Filename string 48 Args []string 49 } 50 51 func (this MixMatch) Gen(folder string, news []string) { 52 if err := os.MkdirAll(folder, 0777); err != nil { 53 panic(err) 54 } 55 data, err := ioutil.ReadFile(this.Filename) 56 if err != nil { 57 panic(err) 58 } 59 content := string(data) 60 for i, old := range this.Old { 61 if !strings.Contains(content, old) { 62 panic(fmt.Errorf("could not find string {%s} to replace with {%s}", old, news[i])) 63 } 64 content = strings.Replace(content, old, news[i], 1) 65 if strings.Contains(content, old) && old != news[i] { 66 panic(fmt.Errorf("found another string {%s} after it was replaced with {%s}", old, news[i])) 67 } 68 } 69 if err = ioutil.WriteFile(filepath.Join(folder, this.Filename), []byte(content), 0666); err != nil { 70 panic(err) 71 } 72 args := append(this.Args, filepath.Join(folder, this.Filename)) 73 var regenerate = exec.Command("protoc", args...) 74 out, err := regenerate.CombinedOutput() 75 76 failed := false 77 scanner := bufio.NewScanner(bytes.NewReader(out)) 78 for scanner.Scan() { 79 text := scanner.Text() 80 fmt.Println("protoc-gen-combo: ", text) 81 if !strings.Contains(text, "WARNING") { 82 failed = true 83 } 84 } 85 86 if err != nil { 87 fmt.Print("protoc-gen-combo: error: ", err) 88 failed = true 89 } 90 91 if failed { 92 os.Exit(1) 93 } 94 } 95 96 func filter(ss []string, flag string) ([]string, string) { 97 s := make([]string, 0, len(ss)) 98 var v string 99 for i := range ss { 100 if strings.Contains(ss[i], flag) { 101 vs := strings.Split(ss[i], "=") 102 v = vs[1] 103 continue 104 } 105 s = append(s, ss[i]) 106 } 107 return s, v 108 } 109 110 func filterArgs(ss []string) ([]string, []string) { 111 var args []string 112 var flags []string 113 for i := range ss { 114 if strings.Contains(ss[i], "=") { 115 flags = append(flags, ss[i]) 116 continue 117 } 118 args = append(args, ss[i]) 119 } 120 return flags, args 121 } 122 123 func main() { 124 flag.String("version", "2.3.0", "minimum protoc version") 125 flag.Bool("default", true, "generate the case where everything is false") 126 flags, args := filterArgs(os.Args[1:]) 127 var min string 128 flags, min = filter(flags, "-version") 129 if len(min) == 0 { 130 min = "2.3.1" 131 } 132 if !version.AtLeast(min) { 133 fmt.Printf("protoc version not high enough to parse this proto file\n") 134 return 135 } 136 if len(args) != 1 { 137 fmt.Printf("protoc-gen-combo expects a filename\n") 138 os.Exit(1) 139 } 140 filename := args[0] 141 var def string 142 flags, def = filter(flags, "-default") 143 if _, err := exec.LookPath("protoc"); err != nil { 144 panic("cannot find protoc in PATH") 145 } 146 m := MixMatch{ 147 Old: []string{ 148 "option (gogoproto.unmarshaler_all) = false;", 149 "option (gogoproto.marshaler_all) = false;", 150 }, 151 Filename: filename, 152 Args: flags, 153 } 154 if def != "false" { 155 m.Gen("./combos/neither/", []string{ 156 "option (gogoproto.unmarshaler_all) = false;", 157 "option (gogoproto.marshaler_all) = false;", 158 }) 159 } 160 m.Gen("./combos/marshaler/", []string{ 161 "option (gogoproto.unmarshaler_all) = false;", 162 "option (gogoproto.marshaler_all) = true;", 163 }) 164 m.Gen("./combos/unmarshaler/", []string{ 165 "option (gogoproto.unmarshaler_all) = true;", 166 "option (gogoproto.marshaler_all) = false;", 167 }) 168 m.Gen("./combos/both/", []string{ 169 "option (gogoproto.unmarshaler_all) = true;", 170 "option (gogoproto.marshaler_all) = true;", 171 }) 172 }