From 4abc8436bc9453e8f90fe166abb7b4a26f0d1c5f Mon Sep 17 00:00:00 2001 From: Alan Donovan Date: Tue, 26 Aug 2014 15:52:40 -0400 Subject: [PATCH] cmd/eg: add -beforeedit flag, which specifies a command to run before editing a file. e.g. chmod +w, checkout. Also: add a TIPS section to the documentation. LGTM=crawshaw R=crawshaw, gri CC=golang-codereviews https://golang.org/cl/136780044 --- cmd/eg/eg.go | 22 +++++++++++++++++++++- refactor/eg/eg.go | 20 ++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/cmd/eg/eg.go b/cmd/eg/eg.go index 6241a022..320e1798 100644 --- a/cmd/eg/eg.go +++ b/cmd/eg/eg.go @@ -8,13 +8,16 @@ import ( "go/printer" "go/token" "os" + "os/exec" "path/filepath" + "strings" "code.google.com/p/go.tools/go/loader" "code.google.com/p/go.tools/refactor/eg" ) var ( + beforeeditFlag = flag.String("beforeedit", "", "A command to exec before each file is edited (e.g. chmod, checkout). Whitespace delimits argument words. The string '{}' is replaced by the file name.") helpFlag = flag.Bool("help", false, "show detailed help message") templateFlag = flag.String("t", "", "template.go file specifying the refactoring") transitiveFlag = flag.Bool("transitive", false, "apply refactoring to all dependencies too") @@ -103,8 +106,25 @@ func doMain() error { continue } filename := iprog.Fset.File(file.Pos()).Name() - fmt.Fprintf(os.Stderr, "=== %s (%d matches):\n", filename, n) + fmt.Fprintf(os.Stderr, "=== %s (%d matches)\n", filename, n) if *writeFlag { + // Run the before-edit command (e.g. "chmod +w", "checkout") if any. + if *beforeeditFlag != "" { + args := strings.Fields(*beforeeditFlag) + // Replace "{}" with the filename, like find(1). + for i := range args { + if i > 0 { + args[i] = strings.Replace(args[i], "{}", filename, -1) + } + } + cmd := exec.Command(args[0], args[1:]...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + if err := cmd.Run(); err != nil { + fmt.Fprintf(os.Stderr, "Warning: edit hook %q failed (%s)\n", + args, err) + } + } if err := eg.WriteAST(iprog.Fset, filename, file); err != nil { fmt.Fprintf(os.Stderr, "Error: %s\n", err) hadErrors = true diff --git a/refactor/eg/eg.go b/refactor/eg/eg.go index c754917f..f080b2ec 100644 --- a/refactor/eg/eg.go +++ b/refactor/eg/eg.go @@ -105,6 +105,26 @@ Imports are added as needed, but they are not removed as needed. Run 'goimports' on the modified file for now. Dot imports are forbidden in the template. + + +TIPS +==== + +Sometimes a little creativity is required to implement the desired +migration. This section lists a few tips and tricks. + +To remove the final parameter from a function, temporarily change the +function signature so that the final parameter is variadic, as this +allows legal calls both with and without the argument. Then use eg to +remove the final argument from all callers, and remove the variadic +parameter by hand. The reverse process can be used to add a final +parameter. + +To add or remove parameters other than the final one, you must do it in +stages: (1) declare a variant function f' with a different name and the +desired parameters; (2) use eg to transform calls to f into calls to f', +changing the arguments as needed; (3) change the declaration of f to +match f'; (4) use eg to rename f' to f in all calls; (5) delete f'. ` // TODO(adonovan): allow the tool to be invoked using relative package