| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 
|  | 2 // Use of this source code is governed by a BSD-style license that can be | 
|  | 3 // found in the LICENSE file. | 
|  | 4 | 
|  | 5 package main | 
|  | 6 | 
|  | 7 import ( | 
|  | 8         "bufio" | 
|  | 9         "flag" | 
|  | 10         "fmt" | 
|  | 11         "io" | 
|  | 12         "os" | 
|  | 13         "sort" | 
|  | 14         "strings" | 
|  | 15         "text/template" | 
|  | 16 | 
|  | 17         "github.com/luci/luci-go/common/errors" | 
|  | 18         "github.com/luci/luci-go/common/flag/stringsetflag" | 
|  | 19 ) | 
|  | 20 | 
|  | 21 type app struct { | 
|  | 22         out io.Writer | 
|  | 23 | 
|  | 24         packageName string | 
|  | 25         typeNames   stringsetflag.Flag | 
|  | 26         outFile     string | 
|  | 27 } | 
|  | 28 | 
|  | 29 const help = `Usage of %s: | 
|  | 30 | 
|  | 31 %s is a go-generator program that generates PropertyConverter implementations | 
|  | 32 for types produced by protoc. It can be used in a go generation file like: | 
|  | 33 | 
|  | 34   //go:generate <protoc command> | 
|  | 35   //go:generate proto-gae -type MessageType -type OtherMessageType | 
|  | 36 | 
|  | 37 This will produce a new file which implements the ToProperty and FromProperty | 
|  | 38 methods for the named types. | 
|  | 39 | 
|  | 40 Options: | 
|  | 41 ` | 
|  | 42 | 
|  | 43 func (a *app) parseArgs(fs *flag.FlagSet, args []string) error { | 
|  | 44         fs.SetOutput(a.out) | 
|  | 45         fs.Usage = func() { | 
|  | 46                 fmt.Fprintf(a.out, help, args[0], args[0]) | 
|  | 47                 fs.PrintDefaults() | 
|  | 48         } | 
|  | 49 | 
|  | 50         fs.Var(&a.typeNames, "type", | 
|  | 51                 "A generated proto.Message type to generate stubs for (required,
      repeatable)") | 
|  | 52         fs.StringVar(&a.outFile, "out", "proto_gae.gen.go", | 
|  | 53                 "The name of the output file") | 
|  | 54 | 
|  | 55         if err := fs.Parse(args[1:]); err != nil { | 
|  | 56                 return err | 
|  | 57         } | 
|  | 58         fail := errors.MultiError(nil) | 
|  | 59         if a.typeNames.Data == nil || a.typeNames.Data.Len() == 0 { | 
|  | 60                 fail = append(fail, errors.New("must specify one or more -type")
     ) | 
|  | 61         } | 
|  | 62         if !strings.HasSuffix(a.outFile, ".go") { | 
|  | 63                 fail = append(fail, errors.New("-output must end with '.go'")) | 
|  | 64         } | 
|  | 65         if len(fail) > 0 { | 
|  | 66                 for _, e := range fail { | 
|  | 67                         fmt.Fprintln(a.out, "error:", e) | 
|  | 68                 } | 
|  | 69                 fmt.Fprintln(a.out) | 
|  | 70                 fs.Usage() | 
|  | 71                 return fail | 
|  | 72         } | 
|  | 73         return nil | 
|  | 74 } | 
|  | 75 | 
|  | 76 var tmpl = template.Must( | 
|  | 77         template.New("main").Parse(`// AUTOGENERATED: Do not edit | 
|  | 78 | 
|  | 79 package {{index . "package"}} | 
|  | 80 | 
|  | 81 import ( | 
|  | 82         "github.com/golang/protobuf/proto" | 
|  | 83 | 
|  | 84         "github.com/luci/gae/service/datastore" | 
|  | 85 ){{range index . "types"}} | 
|  | 86 | 
|  | 87 var _ datastore.PropertyConverter = (*{{.}})(nil) | 
|  | 88 | 
|  | 89 // ToProperty implements datastore.PropertyConverter. It causes an embedded | 
|  | 90 // '{{.}}' to serialize to an unindexed '[]byte' when used with the | 
|  | 91 // "github.com/luci/gae" library. | 
|  | 92 func (p *{{.}}) ToProperty() (prop datastore.Property, err error) { | 
|  | 93         data, err := proto.Marshal(p) | 
|  | 94         if err == nil { | 
|  | 95                 prop.SetValue(data, datastore.NoIndex) | 
|  | 96         } | 
|  | 97         return | 
|  | 98 } | 
|  | 99 | 
|  | 100 // FromProperty implements datastore.PropertyConverter. It parses a '[]byte' | 
|  | 101 // into an embedded '{{.}}' when used with the "github.com/luci/gae" library. | 
|  | 102 func (p *{{.}}) FromProperty(prop datastore.Property) error { | 
|  | 103         data, err := prop.Project(datastore.PTBytes) | 
|  | 104         if err != nil { | 
|  | 105                 return err | 
|  | 106         } | 
|  | 107         return proto.Unmarshal(data.([]byte), p) | 
|  | 108 }{{end}} | 
|  | 109 `)) | 
|  | 110 | 
|  | 111 func (a *app) writeTo(w io.Writer) error { | 
|  | 112         typeNames := a.typeNames.Data.ToSlice() | 
|  | 113         sort.Strings(typeNames) | 
|  | 114 | 
|  | 115         return tmpl.Execute(w, map[string]interface{}{ | 
|  | 116                 "package": a.packageName, | 
|  | 117                 "types":   typeNames, | 
|  | 118         }) | 
|  | 119 } | 
|  | 120 | 
|  | 121 func (a *app) main() { | 
|  | 122         if err := a.parseArgs(flag.NewFlagSet(os.Args[0], flag.ContinueOnError),
      os.Args); err != nil { | 
|  | 123                 os.Exit(1) | 
|  | 124         } | 
|  | 125         ofile, err := os.Create(a.outFile) | 
|  | 126         if err != nil { | 
|  | 127                 fmt.Fprintf(a.out, "error: %s", err) | 
|  | 128                 os.Exit(2) | 
|  | 129         } | 
|  | 130         closeFn := func(delete bool) { | 
|  | 131                 if ofile != nil { | 
|  | 132                         if err := ofile.Close(); err != nil { | 
|  | 133                                 fmt.Fprintf(a.out, "error while closing file: %s
     ", err) | 
|  | 134                         } | 
|  | 135                         if delete { | 
|  | 136                                 if err := os.Remove(a.outFile); err != nil { | 
|  | 137                                         fmt.Fprintf(a.out, "failed to remove fil
     e!") | 
|  | 138                                 } | 
|  | 139                         } | 
|  | 140                 } | 
|  | 141                 ofile = nil | 
|  | 142         } | 
|  | 143         defer closeFn(false) | 
|  | 144         buf := bufio.NewWriter(ofile) | 
|  | 145         err = a.writeTo(buf) | 
|  | 146         if err != nil { | 
|  | 147                 fmt.Fprintf(a.out, "error while writing: %s", err) | 
|  | 148                 closeFn(true) | 
|  | 149                 os.Exit(3) | 
|  | 150         } | 
|  | 151         if err := buf.Flush(); err != nil { | 
|  | 152                 fmt.Fprintf(a.out, "error while writing: %s", err) | 
|  | 153                 closeFn(true) | 
|  | 154                 os.Exit(4) | 
|  | 155         } | 
|  | 156 } | 
|  | 157 | 
|  | 158 func main() { | 
|  | 159         (&app{out: os.Stderr, packageName: os.Getenv("GOPACKAGE")}).main() | 
|  | 160 } | 
| OLD | NEW | 
|---|