From 4bd94ee7380717f0ba9caa92217e81f20b90bb8b Mon Sep 17 00:00:00 2001 From: Robert van Gent Date: Thu, 15 Nov 2018 17:27:01 -0800 Subject: [PATCH 01/10] wire: support multiple packages in Generate --- wire/cmd/wire/main.go | 39 ++++++++++++++-------- wire/internal/wire/wire.go | 58 ++++++++++++++++++--------------- wire/internal/wire/wire_test.go | 9 ++++- 3 files changed, 65 insertions(+), 41 deletions(-) diff --git a/wire/cmd/wire/main.go b/wire/cmd/wire/main.go index ab9a193c6..bf8aa2d6a 100644 --- a/wire/cmd/wire/main.go +++ b/wire/cmd/wire/main.go @@ -41,8 +41,6 @@ func main() { case len(os.Args) == 2 && (os.Args[1] == "help" || os.Args[1] == "-h" || os.Args[1] == "-help" || os.Args[1] == "--help"): fmt.Fprintln(os.Stderr, usage) os.Exit(0) - case len(os.Args) == 1 || len(os.Args) == 2 && os.Args[1] == "gen": - err = generate(".") case len(os.Args) == 2 && os.Args[1] == "show": err = show(".") case len(os.Args) > 2 && os.Args[1] == "show": @@ -51,10 +49,15 @@ func main() { err = check(".") case len(os.Args) > 2 && os.Args[1] == "check": err = check(os.Args[2:]...) - case len(os.Args) == 2: - err = generate(os.Args[1]) - case len(os.Args) == 3 && os.Args[1] == "gen": - err = generate(os.Args[2]) + case len(os.Args) == 2 && os.Args[1] == "gen": + err = generate(".") + case len(os.Args) > 2 && os.Args[1] == "gen": + err = generate(os.Args[2:]...) + // No explicit command given, assume "gen". + case len(os.Args) == 1: + err = generate(".") + case len(os.Args) > 1: + err = generate(os.Args[1:]...) default: fmt.Fprintln(os.Stderr, usage) os.Exit(64) @@ -65,24 +68,34 @@ func main() { } } -// generate runs the gen subcommand. Given a package, gen will create -// the wire_gen.go file. -func generate(pkg string) error { +// generate runs the gen subcommand. +// +// Given one or more packages, gen will create the wire_gen.go file for each. +func generate(pkgs ...string) error { wd, err := os.Getwd() if err != nil { return err } - out, errs := wire.Generate(context.Background(), wd, os.Environ(), pkg) + outs, errs := wire.Generate(context.Background(), wd, os.Environ(), pkgs) if len(errs) > 0 { logErrors(errs) return errors.New("generate failed") } - if len(out.Content) == 0 { + if len(outs) == 0 { // No Wire directives, don't write anything. - fmt.Fprintln(os.Stderr, "wire: no injector found for", pkg) + fmt.Fprintln(os.Stderr, "wire: no injector found") return nil } - return out.Commit() + for _, out := range outs { + if err := out.Commit(); err != nil { + errs = append(errs, err) + } + } + if len(errs) > 0 { + logErrors(errs) + return errors.New("some writes failed") + } + return nil } // show runs the show subcommand. diff --git a/wire/internal/wire/wire.go b/wire/internal/wire/wire.go index c11c97adb..b76d5730c 100644 --- a/wire/internal/wire/wire.go +++ b/wire/internal/wire/wire.go @@ -41,6 +41,7 @@ import ( // GeneratedFile stores the content of a call to Generate and the // desired on-disk location of the file. type GeneratedFile struct { + Package string Path string Content []byte } @@ -53,8 +54,8 @@ func (gen GeneratedFile) Commit() error { return ioutil.WriteFile(gen.Path, gen.Content, 0666) } -// Generate performs dependency injection for a single package, -// returning the gofmt'd Go source code. The package pattern is defined +// Generate performs dependency injection for the packages that match the given +// patterns, returning the gofmt'd Go source code. The package pattern is defined // by the underlying build system. For the go tool, this is described at // https://golang.org/cmd/go/#hdr-Package_lists_and_patterns // @@ -63,34 +64,37 @@ func (gen GeneratedFile) Commit() error { // env is nil or empty, it is interpreted as an empty set of variables. // In case of duplicate environment variables, the last one in the list // takes precedence. -func Generate(ctx context.Context, wd string, env []string, pkgPattern string) (GeneratedFile, []error) { - pkgs, errs := load(ctx, wd, env, []string{pkgPattern}) +func Generate(ctx context.Context, wd string, env []string, patterns []string) ([]GeneratedFile, []error) { + pkgs, errs := load(ctx, wd, env, patterns) if len(errs) > 0 { - return GeneratedFile{}, errs + return nil, errs } - if len(pkgs) != 1 { - // This is more of a violated precondition than anything else. - return GeneratedFile{}, []error{fmt.Errorf("load: got %d packages", len(pkgs))} - } - outDir, err := detectOutputDir(pkgs[0].GoFiles) - if err != nil { - return GeneratedFile{}, []error{fmt.Errorf("load: %v", err)} - } - outFname := filepath.Join(outDir, "wire_gen.go") - g := newGen(pkgs[0]) - injectorFiles, errs := generateInjectors(g, pkgs[0]) - if len(errs) > 0 { - return GeneratedFile{}, errs - } - copyNonInjectorDecls(g, injectorFiles, pkgs[0].TypesInfo) - goSrc := g.frame() - fmtSrc, err := format.Source(goSrc) - if err != nil { - // This is likely a bug from a poorly generated source file. - // Return an error and the unformatted source. - return GeneratedFile{Path: outFname, Content: goSrc}, []error{err} + generated := make([]GeneratedFile, 0, len(pkgs)) + ec := new(errorCollector) + for _, pkg := range pkgs { + outDir, err := detectOutputDir(pkg.GoFiles) + if err != nil { + ec.add(fmt.Errorf("load %s: %v", pkg.Name, err)) + } + outFname := filepath.Join(outDir, "wire_gen.go") + g := newGen(pkg) + injectorFiles, errs := generateInjectors(g, pkg) + if len(errs) > 0 { + ec.add(errs...) + } + copyNonInjectorDecls(g, injectorFiles, pkg.TypesInfo) + goSrc := g.frame() + fmtSrc, err := format.Source(goSrc) + if err != nil { + // This is likely a bug from a poorly generated source file. + // Add an error but also return the unformatted source. + ec.add(err) + } else { + goSrc = fmtSrc + } + generated = append(generated, GeneratedFile{Package: pkg.Name, Path: outFname, Content: fmtSrc}) } - return GeneratedFile{Path: outFname, Content: fmtSrc}, nil + return generated, ec.errors } func detectOutputDir(paths []string) (string, error) { diff --git a/wire/internal/wire/wire_test.go b/wire/internal/wire/wire_test.go index f554b12e8..e016a8dc5 100644 --- a/wire/internal/wire/wire_test.go +++ b/wire/internal/wire/wire_test.go @@ -88,7 +88,14 @@ func TestWire(t *testing.T) { t.Fatal(err) } wd := filepath.Join(gopath, "src", "example.com") - gen, errs := Generate(ctx, wd, append(os.Environ(), "GOPATH="+gopath), test.pkg) + gens, errs := Generate(ctx, wd, append(os.Environ(), "GOPATH="+gopath), []string{test.pkg}) + if len(gens) > 1 { + t.Fatalf("got %d generated files, want 0-1", len(gens)) + } + var gen GeneratedFile + if len(gens) > 0 { + gen = gens[0] + } if len(gen.Content) > 0 { defer t.Logf("wire_gen.go:\n%s", gen.Content) } From 7d2993dc2062f8c16aa13e93bc30a433543ae1ba Mon Sep 17 00:00:00 2001 From: Ross Light Date: Fri, 16 Nov 2018 10:13:02 -0800 Subject: [PATCH 02/10] Update wire/cmd/wire/main.go Co-Authored-By: vangent --- wire/cmd/wire/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wire/cmd/wire/main.go b/wire/cmd/wire/main.go index bf8aa2d6a..da21e6ae8 100644 --- a/wire/cmd/wire/main.go +++ b/wire/cmd/wire/main.go @@ -83,7 +83,7 @@ func generate(pkgs ...string) error { } if len(outs) == 0 { // No Wire directives, don't write anything. - fmt.Fprintln(os.Stderr, "wire: no injector found") + fmt.Fprintln(os.Stderr, "wire: no injectors found") return nil } for _, out := range outs { From c1a579f2dbed266e508ec9b520ed774097ca4c51 Mon Sep 17 00:00:00 2001 From: Robert van Gent Date: Fri, 16 Nov 2018 10:56:21 -0800 Subject: [PATCH 03/10] ckpt --- wire/cmd/wire/main.go | 21 +++++++++------ wire/internal/wire/wire.go | 47 ++++++++++++++++++++------------- wire/internal/wire/wire_test.go | 15 ++++++----- 3 files changed, 51 insertions(+), 32 deletions(-) diff --git a/wire/cmd/wire/main.go b/wire/cmd/wire/main.go index 360ca2571..05cbb0f24 100644 --- a/wire/cmd/wire/main.go +++ b/wire/cmd/wire/main.go @@ -82,18 +82,23 @@ func generate(pkgs ...string) error { return errors.New("generate failed") } if len(outs) == 0 { - // No Wire directives, don't write anything. - fmt.Fprintln(os.Stderr, "wire: no injector found") return nil } for _, out := range outs { - if err := out.Commit(); err != nil { - errs = append(errs, err) + if len(out.Errs) > 0 { + fmt.Fprintf(os.Stderr, "%s: generate failed", out.Package) + logErrors(out.Errs) + } + if len(out.Content) == 0 { + // No Wire directives, don't write anything. + fmt.Fprintf(os.Stderr, "%s: no injector found", out.Package) + } else { + if err := out.Commit(); err == nil { + fmt.Fprintf(os.Stderr, "%s: wrote %s", out.Package, out.Path) + } else { + fmt.Fprintf(os.Stderr, "%s: failed to write %s: %v", out.Package, out.Path, err) + } } - } - if len(errs) > 0 { - logErrors(errs) - return errors.New("some writes failed") } return nil } diff --git a/wire/internal/wire/wire.go b/wire/internal/wire/wire.go index 3398cd6d1..2cf3b9bc6 100644 --- a/wire/internal/wire/wire.go +++ b/wire/internal/wire/wire.go @@ -38,16 +38,22 @@ import ( "golang.org/x/tools/go/packages" ) -// GeneratedFile stores the content of a call to Generate and the -// desired on-disk location of the file. -type GeneratedFile struct { +// GenerateResult stores the result for a package from a call to Generate. +type GenerateResult struct { + // Package is the package's name. Package string - Path string + // Path is the path where the generated output should be written. + // May be empty if there were errors. + Path string + // Content is the gofmt'd source code that was generated. May be nil if + // there were errors during generation. Content []byte + // Errs is a slice of errors identified during generation. + Errs []error } // Commit writes the generated file to disk. -func (gen GeneratedFile) Commit() error { +func (gen GenerateResult) Commit() error { if len(gen.Content) == 0 { return nil } @@ -55,8 +61,8 @@ func (gen GeneratedFile) Commit() error { } // Generate performs dependency injection for the packages that match the given -// patterns, returning the gofmt'd Go source code. The package pattern is defined -// by the underlying build system. For the go tool, this is described at +// patterns, return a GenerateResult for each package. The package pattern is +// defined by the underlying build system. For the go tool, this is described at // https://golang.org/cmd/go/#hdr-Package_lists_and_patterns // // wd is the working directory and env is the set of environment @@ -64,37 +70,42 @@ func (gen GeneratedFile) Commit() error { // env is nil or empty, it is interpreted as an empty set of variables. // In case of duplicate environment variables, the last one in the list // takes precedence. -func Generate(ctx context.Context, wd string, env []string, patterns []string) ([]GeneratedFile, []error) { +// +// Generate may return one or more errors if it failed to load the packages. +func Generate(ctx context.Context, wd string, env []string, patterns []string) ([]*GenerateResult, []error) { pkgs, errs := load(ctx, wd, env, patterns) if len(errs) > 0 { return nil, errs } - generated := make([]GeneratedFile, 0, len(pkgs)) - ec := new(errorCollector) - for _, pkg := range pkgs { + generated := make([]*GenerateResult, len(pkgs)) + for i, pkg := range pkgs { + result := &GenerateResult{Package: pkg.Name} + generated[i] = result outDir, err := detectOutputDir(pkg.GoFiles) if err != nil { - ec.add(fmt.Errorf("load %s: %v", pkg.Name, err)) + result.Errs = append(result.Errs, err) + continue } - outFname := filepath.Join(outDir, "wire_gen.go") + result.Path = filepath.Join(outDir, "wire_gen.go") g := newGen(pkg) injectorFiles, errs := generateInjectors(g, pkg) if len(errs) > 0 { - ec.add(errs...) + result.Errs = errs + continue } copyNonInjectorDecls(g, injectorFiles, pkg.TypesInfo) goSrc := g.frame() fmtSrc, err := format.Source(goSrc) if err != nil { // This is likely a bug from a poorly generated source file. - // Add an error but also return the unformatted source. - ec.add(err) + // Add an error but also the unformatted source. + result.Errs = append(result.Errs, err) } else { goSrc = fmtSrc } - generated = append(generated, GeneratedFile{Package: pkg.Name, Path: outFname, Content: fmtSrc}) + result.Content = goSrc } - return generated, ec.errors + return generated, nil } func detectOutputDir(paths []string) (string, error) { diff --git a/wire/internal/wire/wire_test.go b/wire/internal/wire/wire_test.go index e016a8dc5..584735365 100644 --- a/wire/internal/wire/wire_test.go +++ b/wire/internal/wire/wire_test.go @@ -89,15 +89,18 @@ func TestWire(t *testing.T) { } wd := filepath.Join(gopath, "src", "example.com") gens, errs := Generate(ctx, wd, append(os.Environ(), "GOPATH="+gopath), []string{test.pkg}) + var gen *GenerateResult if len(gens) > 1 { - t.Fatalf("got %d generated files, want 0-1", len(gens)) + t.Fatalf("got %d generated files, want 0 or 1", len(gens)) } - var gen GeneratedFile - if len(gens) > 0 { + if len(gens) == 1 { gen = gens[0] - } - if len(gen.Content) > 0 { - defer t.Logf("wire_gen.go:\n%s", gen.Content) + if len(gen.Errs) > 0 { + errs = append(errs, gen.Errs...) + } + if len(gen.Content) > 0 { + defer t.Logf("wire_gen.go:\n%s", gen.Content) + } } if len(errs) > 0 { gotErrStrings := make([]string, len(errs)) From d6db84acc7c88ab01c154c55292ae916e4be62c3 Mon Sep 17 00:00:00 2001 From: Robert van Gent Date: Fri, 16 Nov 2018 11:02:24 -0800 Subject: [PATCH 04/10] GeneratedFile -> GenerateResult --- wire/cmd/wire/main.go | 15 +++++++-------- wire/internal/wire/wire.go | 14 +++++++------- wire/internal/wire/wire_test.go | 4 ++-- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/wire/cmd/wire/main.go b/wire/cmd/wire/main.go index 05cbb0f24..b417e1b32 100644 --- a/wire/cmd/wire/main.go +++ b/wire/cmd/wire/main.go @@ -86,18 +86,17 @@ func generate(pkgs ...string) error { } for _, out := range outs { if len(out.Errs) > 0 { - fmt.Fprintf(os.Stderr, "%s: generate failed", out.Package) + fmt.Fprintf(os.Stderr, "%s: generate failed\n", out.PkgPath) logErrors(out.Errs) } if len(out.Content) == 0 { - // No Wire directives, don't write anything. - fmt.Fprintf(os.Stderr, "%s: no injector found", out.Package) + // No Wire output. Maybe errors, maybe no Wire directives. + continue + } + if err := out.Commit(); err == nil { + fmt.Fprintf(os.Stderr, "%s: wrote %s\n", out.PkgPath, out.OutputPath) } else { - if err := out.Commit(); err == nil { - fmt.Fprintf(os.Stderr, "%s: wrote %s", out.Package, out.Path) - } else { - fmt.Fprintf(os.Stderr, "%s: failed to write %s: %v", out.Package, out.Path, err) - } + fmt.Fprintf(os.Stderr, "%s: failed to write %s: %v\n", out.PkgPath, out.OutputPath, err) } } return nil diff --git a/wire/internal/wire/wire.go b/wire/internal/wire/wire.go index 2cf3b9bc6..9b92015be 100644 --- a/wire/internal/wire/wire.go +++ b/wire/internal/wire/wire.go @@ -40,11 +40,11 @@ import ( // GenerateResult stores the result for a package from a call to Generate. type GenerateResult struct { - // Package is the package's name. - Package string - // Path is the path where the generated output should be written. + // PkgPath is the package's PkgPath. + PkgPath string + // OutputPath is the path where the generated output should be written. // May be empty if there were errors. - Path string + OutputPath string // Content is the gofmt'd source code that was generated. May be nil if // there were errors during generation. Content []byte @@ -57,7 +57,7 @@ func (gen GenerateResult) Commit() error { if len(gen.Content) == 0 { return nil } - return ioutil.WriteFile(gen.Path, gen.Content, 0666) + return ioutil.WriteFile(gen.OutputPath, gen.Content, 0666) } // Generate performs dependency injection for the packages that match the given @@ -79,14 +79,14 @@ func Generate(ctx context.Context, wd string, env []string, patterns []string) ( } generated := make([]*GenerateResult, len(pkgs)) for i, pkg := range pkgs { - result := &GenerateResult{Package: pkg.Name} + result := &GenerateResult{PkgPath: pkg.PkgPath} generated[i] = result outDir, err := detectOutputDir(pkg.GoFiles) if err != nil { result.Errs = append(result.Errs, err) continue } - result.Path = filepath.Join(outDir, "wire_gen.go") + result.OutputPath = filepath.Join(outDir, "wire_gen.go") g := newGen(pkg) injectorFiles, errs := generateInjectors(g, pkg) if len(errs) > 0 { diff --git a/wire/internal/wire/wire_test.go b/wire/internal/wire/wire_test.go index 584735365..118740828 100644 --- a/wire/internal/wire/wire_test.go +++ b/wire/internal/wire/wire_test.go @@ -127,9 +127,9 @@ func TestWire(t *testing.T) { t.Fatal("wire succeeded; want error") } outPathSane := true - if prefix := gopath + string(os.PathSeparator) + "src" + string(os.PathSeparator); !strings.HasPrefix(gen.Path, prefix) { + if prefix := gopath + string(os.PathSeparator) + "src" + string(os.PathSeparator); !strings.HasPrefix(gen.OutputPath, prefix) { outPathSane = false - t.Errorf("suggested output path = %q; want to start with %q", gen.Path, prefix) + t.Errorf("suggested output path = %q; want to start with %q", gen.OutputPath, prefix) } if *setup.Record { From 8a8cd0156a21825c9d472d1cf398d5f904475b18 Mon Sep 17 00:00:00 2001 From: Robert van Gent Date: Fri, 16 Nov 2018 11:05:21 -0800 Subject: [PATCH 05/10] ckpt --- wire/cmd/wire/main.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/wire/cmd/wire/main.go b/wire/cmd/wire/main.go index b417e1b32..c4017041f 100644 --- a/wire/cmd/wire/main.go +++ b/wire/cmd/wire/main.go @@ -84,10 +84,12 @@ func generate(pkgs ...string) error { if len(outs) == 0 { return nil } + success := true for _, out := range outs { if len(out.Errs) > 0 { fmt.Fprintf(os.Stderr, "%s: generate failed\n", out.PkgPath) logErrors(out.Errs) + success = false } if len(out.Content) == 0 { // No Wire output. Maybe errors, maybe no Wire directives. @@ -99,6 +101,9 @@ func generate(pkgs ...string) error { fmt.Fprintf(os.Stderr, "%s: failed to write %s: %v\n", out.PkgPath, out.OutputPath, err) } } + if !success { + return errors.New("generate failed") + } return nil } From 2b31d3457298de69599c395480496fba92e681bd Mon Sep 17 00:00:00 2001 From: Robert van Gent Date: Fri, 16 Nov 2018 11:05:48 -0800 Subject: [PATCH 06/10] ckpt --- wire/cmd/wire/main.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wire/cmd/wire/main.go b/wire/cmd/wire/main.go index c4017041f..e58b61528 100644 --- a/wire/cmd/wire/main.go +++ b/wire/cmd/wire/main.go @@ -99,10 +99,11 @@ func generate(pkgs ...string) error { fmt.Fprintf(os.Stderr, "%s: wrote %s\n", out.PkgPath, out.OutputPath) } else { fmt.Fprintf(os.Stderr, "%s: failed to write %s: %v\n", out.PkgPath, out.OutputPath, err) + success = false } } if !success { - return errors.New("generate failed") + return errors.New("at least one generate failure") } return nil } From cf840b5f6eeeddb49d09c376c4609d203b9b7235 Mon Sep 17 00:00:00 2001 From: Robert van Gent Date: Thu, 15 Nov 2018 15:41:17 -0800 Subject: [PATCH 07/10] ckpt --- go.mod | 1 + samples/guestbook/wire_gen.go | 3 ++- wire/cmd/wire/main.go | 33 ++++++++++++++++++++++++++++++++- wire/internal/wire/wire.go | 12 ++++++++++++ 4 files changed, 47 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 4ee9482ee..12a8fc71f 100644 --- a/go.mod +++ b/go.mod @@ -54,6 +54,7 @@ require ( github.com/mattn/goveralls v0.0.2 // indirect github.com/opencensus-integrations/ocsql v0.1.1 github.com/pkg/errors v0.8.0 // indirect + github.com/pmezard/go-difflib v1.0.0 github.com/prometheus/client_golang v0.9.0 // indirect github.com/prometheus/common v0.0.0-20181015124227-bcb74de08d37 // indirect github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d // indirect diff --git a/samples/guestbook/wire_gen.go b/samples/guestbook/wire_gen.go index c0fbaab43..46c77920c 100644 --- a/samples/guestbook/wire_gen.go +++ b/samples/guestbook/wire_gen.go @@ -17,6 +17,7 @@ import ( "github.com/google/go-cloud/blob/gcsblob" "github.com/google/go-cloud/blob/s3blob" "github.com/google/go-cloud/gcp" + "github.com/google/go-cloud/gcp/cloudsql" "github.com/google/go-cloud/mysql/cloudmysql" "github.com/google/go-cloud/mysql/rdsmysql" "github.com/google/go-cloud/requestlog" @@ -114,7 +115,7 @@ func setupGCP(ctx context.Context, flags *cliFlags) (*application, func(), error if err != nil { return nil, nil, err } - remoteCertSource := cloudmysql.NewCertSource(httpClient) + remoteCertSource := cloudsql.NewCertSource(httpClient) projectID, err := gcp.DefaultProjectID(credentials) if err != nil { return nil, nil, err diff --git a/wire/cmd/wire/main.go b/wire/cmd/wire/main.go index c92ee2bdd..f810361be 100644 --- a/wire/cmd/wire/main.go +++ b/wire/cmd/wire/main.go @@ -33,7 +33,7 @@ import ( "golang.org/x/tools/go/types/typeutil" ) -const usage = "usage: wire [gen] [PKG] | wire show [...] | wire check [...]" +const usage = "usage: wire [gen] [PKG] | wire show [...] | wire check [...] | wire diff [...]" func main() { var err error @@ -51,6 +51,10 @@ func main() { err = check(".") case len(os.Args) > 2 && os.Args[1] == "check": err = check(os.Args[2:]...) + case len(os.Args) == 2 && os.Args[1] == "diff": + err = diff(".") + case len(os.Args) > 2 && os.Args[1] == "diff": + err = diff(os.Args[2:]...) case len(os.Args) == 2: err = generate(os.Args[1]) case len(os.Args) == 3 && os.Args[1] == "gen": @@ -85,6 +89,33 @@ func generate(pkg string) error { return out.Commit() } +// diff runs the diff subcommand. Given a package, diff will generate +// the content for the wire_gen.go file, and output the diff against the +// existing file. +func diff(pkgs ...string) error { + wd, err := os.Getwd() + if err != nil { + return err + } + for _, pkg := range pkgs { + fmt.Println(pkg) + out, errs := wire.Generate(context.Background(), wd, os.Environ(), pkg) + if len(errs) > 0 { + logErrors(errs) + return errors.New("generate failed") + } + if len(out.Content) == 0 { + // No Wire directives, don't write anything. + fmt.Fprintln(os.Stderr, "wire: no injector found for", pkg) + continue + } + if err := out.Diff(os.Stderr); err != nil { + return err + } + } + return nil +} + // show runs the show subcommand. // // Given one or more packages, show will find all the provider sets diff --git a/wire/internal/wire/wire.go b/wire/internal/wire/wire.go index d1dcffb04..f5c0a0562 100644 --- a/wire/internal/wire/wire.go +++ b/wire/internal/wire/wire.go @@ -26,6 +26,7 @@ import ( "go/printer" "go/token" "go/types" + "io" "io/ioutil" "path/filepath" "sort" @@ -34,6 +35,7 @@ import ( "unicode" "unicode/utf8" + "github.com/pmezard/go-difflib/difflib" "golang.org/x/tools/go/ast/astutil" "golang.org/x/tools/go/packages" ) @@ -53,6 +55,16 @@ func (gen GeneratedFile) Commit() error { return ioutil.WriteFile(gen.Path, gen.Content, 0666) } +// Diff writes a diff of the current file on disk vs the generated file to out. +func (gen GeneratedFile) Diff(out io.Writer) error { + // Assume the current file is empty if we can't read it. + cur, _ := ioutil.ReadFile(gen.Path) + return difflib.WriteUnifiedDiff(out, difflib.UnifiedDiff{ + A: difflib.SplitLines(string(cur)), + B: difflib.SplitLines(string(gen.Content)), + }) +} + // Generate performs dependency injection for a single package, // returning the gofmt'd Go source code. The package pattern is defined // by the underlying build system. For the go tool, this is described at From 0d9bfaf84155d98de711546da9f070034a3642e8 Mon Sep 17 00:00:00 2001 From: Robert van Gent Date: Fri, 16 Nov 2018 11:46:16 -0800 Subject: [PATCH 08/10] ckpt --- samples/guestbook/wire_gen.go | 3 +-- wire/cmd/wire/main.go | 42 ++++++++++++++++++++++++----------- wire/internal/wire/wire.go | 2 +- 3 files changed, 31 insertions(+), 16 deletions(-) diff --git a/samples/guestbook/wire_gen.go b/samples/guestbook/wire_gen.go index 46c77920c..c0fbaab43 100644 --- a/samples/guestbook/wire_gen.go +++ b/samples/guestbook/wire_gen.go @@ -17,7 +17,6 @@ import ( "github.com/google/go-cloud/blob/gcsblob" "github.com/google/go-cloud/blob/s3blob" "github.com/google/go-cloud/gcp" - "github.com/google/go-cloud/gcp/cloudsql" "github.com/google/go-cloud/mysql/cloudmysql" "github.com/google/go-cloud/mysql/rdsmysql" "github.com/google/go-cloud/requestlog" @@ -115,7 +114,7 @@ func setupGCP(ctx context.Context, flags *cliFlags) (*application, func(), error if err != nil { return nil, nil, err } - remoteCertSource := cloudsql.NewCertSource(httpClient) + remoteCertSource := cloudmysql.NewCertSource(httpClient) projectID, err := gcp.DefaultProjectID(credentials) if err != nil { return nil, nil, err diff --git a/wire/cmd/wire/main.go b/wire/cmd/wire/main.go index 5b088b045..51358b670 100644 --- a/wire/cmd/wire/main.go +++ b/wire/cmd/wire/main.go @@ -112,30 +112,46 @@ func generate(pkgs ...string) error { return nil } -// diff runs the diff subcommand. Given a package, diff will generate -// the content for the wire_gen.go file, and output the diff against the -// existing file. +// diff runs the diff subcommand. +// +// Given one or more packages, diff will generate the content for the +// wire_gen.go file, and output the diff against the existing file. func diff(pkgs ...string) error { wd, err := os.Getwd() if err != nil { return err } - for _, pkg := range pkgs { - fmt.Println(pkg) - out, errs := wire.Generate(context.Background(), wd, os.Environ(), pkg) - if len(errs) > 0 { - logErrors(errs) - return errors.New("generate failed") + outs, errs := wire.Generate(context.Background(), wd, os.Environ(), pkgs) + if len(errs) > 0 { + logErrors(errs) + return errors.New("generate failed") + } + if len(outs) == 0 { + return nil + } + success := true + for _, out := range outs { + if len(out.Errs) > 0 { + fmt.Fprintf(os.Stderr, "%s: generate failed\n", out.PkgPath) + logErrors(out.Errs) + success = false } if len(out.Content) == 0 { - // No Wire directives, don't write anything. - fmt.Fprintln(os.Stderr, "wire: no injector found for", pkg) + // No Wire output. Maybe errors, maybe no Wire directives. continue } - if err := out.Diff(os.Stderr); err != nil { - return err + if diff, err := out.Diff(); err == nil { + if diff != "" { + fmt.Fprintf(os.Stderr, "%s: diff from %s:\n%s", out.PkgPath, out.OutputPath, diff) + } + } else { + fmt.Fprintf(os.Stderr, "%s: failed to diff %s: %v\n", out.PkgPath, out.OutputPath, err) + success = false } } + if !success { + return errors.New("at least one generate failure") + } return nil } diff --git a/wire/internal/wire/wire.go b/wire/internal/wire/wire.go index a1027059e..6da2a4a81 100644 --- a/wire/internal/wire/wire.go +++ b/wire/internal/wire/wire.go @@ -65,7 +65,7 @@ func (gen GenerateResult) Commit() error { func (gen GenerateResult) Diff() (string, error) { // Assume the current file is empty if we can't read it. cur, _ := ioutil.ReadFile(gen.OutputPath) - return difflib.GetUnifiedDiffString(out, difflib.UnifiedDiff{ + return difflib.GetUnifiedDiffString(difflib.UnifiedDiff{ A: difflib.SplitLines(string(cur)), B: difflib.SplitLines(string(gen.Content)), }) From a1d9a09d80eef84568b01250f677691f44a3a99f Mon Sep 17 00:00:00 2001 From: Robert van Gent Date: Fri, 16 Nov 2018 15:52:42 -0800 Subject: [PATCH 09/10] ckpt --- wire/cmd/wire/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wire/cmd/wire/main.go b/wire/cmd/wire/main.go index 51358b670..d93c40a66 100644 --- a/wire/cmd/wire/main.go +++ b/wire/cmd/wire/main.go @@ -33,7 +33,7 @@ import ( "golang.org/x/tools/go/types/typeutil" ) -const usage = "usage: wire [gen] [PKG] | wire show [...] | wire check [...] | wire diff [...]" +const usage = "usage: wire [gen|diff|show|check] [...]" func main() { var err error From 537749602aa000d9181379cc9c705e2fbb6e3678 Mon Sep 17 00:00:00 2001 From: Robert van Gent Date: Tue, 27 Nov 2018 13:52:42 -0800 Subject: [PATCH 10/10] move difflib dependency to cmd/main --- go.mod | 2 +- wire/cmd/wire/main.go | 9 ++++++++- wire/internal/wire/wire.go | 11 ----------- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/go.mod b/go.mod index 12a8fc71f..f1ac9c484 100644 --- a/go.mod +++ b/go.mod @@ -37,7 +37,7 @@ require ( github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c // indirect github.com/google/go-cmp v0.2.0 github.com/google/martian v2.1.0+incompatible // indirect - github.com/googleapis/gax-go v2.0.0+incompatible // indirect + github.com/googleapis/gax-go v2.0.0+incompatible github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 // indirect github.com/gorilla/context v1.1.1 // indirect github.com/gorilla/mux v1.6.2 diff --git a/wire/cmd/wire/main.go b/wire/cmd/wire/main.go index d93c40a66..18224f67b 100644 --- a/wire/cmd/wire/main.go +++ b/wire/cmd/wire/main.go @@ -23,6 +23,7 @@ import ( "fmt" "go/token" "go/types" + "io/ioutil" "os" "reflect" "sort" @@ -30,6 +31,7 @@ import ( "strings" "github.com/google/go-cloud/wire/internal/wire" + "github.com/pmezard/go-difflib/difflib" "golang.org/x/tools/go/types/typeutil" ) @@ -140,7 +142,12 @@ func diff(pkgs ...string) error { // No Wire output. Maybe errors, maybe no Wire directives. continue } - if diff, err := out.Diff(); err == nil { + // Assumes the current file is empty if we can't read it. + cur, _ := ioutil.ReadFile(out.OutputPath) + if diff, err := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{ + A: difflib.SplitLines(string(cur)), + B: difflib.SplitLines(string(out.Content)), + }); err == nil { if diff != "" { fmt.Fprintf(os.Stderr, "%s: diff from %s:\n%s", out.PkgPath, out.OutputPath, diff) } diff --git a/wire/internal/wire/wire.go b/wire/internal/wire/wire.go index 33d732d14..a2d39c288 100644 --- a/wire/internal/wire/wire.go +++ b/wire/internal/wire/wire.go @@ -34,7 +34,6 @@ import ( "unicode" "unicode/utf8" - "github.com/pmezard/go-difflib/difflib" "golang.org/x/tools/go/ast/astutil" "golang.org/x/tools/go/packages" ) @@ -61,16 +60,6 @@ func (gen GenerateResult) Commit() error { return ioutil.WriteFile(gen.OutputPath, gen.Content, 0666) } -// Diff writes a diff of the current file on disk vs the generated file to out. -func (gen GenerateResult) Diff() (string, error) { - // Assume the current file is empty if we can't read it. - cur, _ := ioutil.ReadFile(gen.OutputPath) - return difflib.GetUnifiedDiffString(difflib.UnifiedDiff{ - A: difflib.SplitLines(string(cur)), - B: difflib.SplitLines(string(gen.Content)), - }) -} - // Generate performs dependency injection for the packages that match the given // patterns, return a GenerateResult for each package. The package pattern is // defined by the underlying build system. For the go tool, this is described at