1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | package main |
8 | |
9 | import ( |
10 | "flag" |
11 | "fmt" |
12 | "go/build" |
13 | "os" |
14 | |
15 | "golang.org/x/tools/go/buildutil" |
16 | "golang.org/x/tools/refactor/rename" |
17 | ) |
18 | |
19 | var ( |
20 | fromFlag = flag.String("from", "", "Import path of package to be moved") |
21 | toFlag = flag.String("to", "", "Destination import path for package") |
22 | vcsMvCmdFlag = flag.String("vcs_mv_cmd", "", `A template for the version control system's "move directory" command, e.g. "git mv {{.Src}} {{.Dst}}"`) |
23 | helpFlag = flag.Bool("help", false, "show usage message") |
24 | ) |
25 | |
26 | func init() { |
27 | flag.Var((*buildutil.TagsFlag)(&build.Default.BuildTags), "tags", buildutil.TagsFlagDoc) |
28 | } |
29 | |
30 | const Usage = `gomvpkg: moves a package, updating import declarations |
31 | |
32 | Usage: |
33 | |
34 | gomvpkg -from <path> -to <path> [-vcs_mv_cmd <template>] |
35 | |
36 | Flags: |
37 | |
38 | -from specifies the import path of the package to be moved |
39 | |
40 | -to specifies the destination import path |
41 | |
42 | -vcs_mv_cmd specifies a shell command to inform the version control system of a |
43 | directory move. The argument is a template using the syntax of the |
44 | text/template package. It has two fields: Src and Dst, the absolute |
45 | paths of the directories. |
46 | |
47 | For example: "git mv {{.Src}} {{.Dst}}" |
48 | |
49 | gomvpkg determines the set of packages that might be affected, including all |
50 | packages importing the 'from' package and any of its subpackages. It will move |
51 | the 'from' package and all its subpackages to the destination path and update all |
52 | imports of those packages to point to its new import path. |
53 | |
54 | gomvpkg rejects moves in which a package already exists at the destination import |
55 | path, or in which a directory already exists at the location the package would be |
56 | moved to. |
57 | |
58 | gomvpkg will not always be able to rename imports when a package's name is changed. |
59 | Import statements may want further cleanup. |
60 | |
61 | gomvpkg's behavior is not defined if any of the packages to be moved are |
62 | imported using dot imports. |
63 | |
64 | Examples: |
65 | |
66 | % gomvpkg -from myproject/foo -to myproject/bar |
67 | |
68 | Move the package with import path "myproject/foo" to the new path |
69 | "myproject/bar". |
70 | |
71 | % gomvpkg -from myproject/foo -to myproject/bar -vcs_mv_cmd "git mv {{.Src}} {{.Dst}}" |
72 | |
73 | Move the package with import path "myproject/foo" to the new path |
74 | "myproject/bar" using "git mv" to execute the directory move. |
75 | ` |
76 | |
77 | func main() { |
78 | flag.Parse() |
79 | |
80 | if len(flag.Args()) > 0 { |
81 | fmt.Fprintln(os.Stderr, "gomvpkg: surplus arguments.") |
82 | os.Exit(1) |
83 | } |
84 | |
85 | if *helpFlag || *fromFlag == "" || *toFlag == "" { |
86 | fmt.Print(Usage) |
87 | return |
88 | } |
89 | |
90 | if err := rename.Move(&build.Default, *fromFlag, *toFlag, *vcsMvCmdFlag); err != nil { |
91 | fmt.Fprintf(os.Stderr, "gomvpkg: %s.\n", err) |
92 | os.Exit(1) |
93 | } |
94 | } |
95 | |