@@ -15,23 +15,25 @@ import (
15
15
)
16
16
17
17
var (
18
- selectAll bool
19
- selectAllNoConfirm bool
20
- dryRun bool
21
- flagVersion bool
18
+ fSelectAll bool
19
+ fSelectAllNoConfirm bool
20
+ fDryRun bool
21
+ fVersion bool
22
+ fSort bool
22
23
)
23
24
24
25
func init () {
25
- flag .BoolVar (& selectAll , "a" , false , "select everything by default" )
26
- flag .BoolVar (& selectAllNoConfirm , "A" , false , "select and update everything without confirmation" )
27
- flag .BoolVar (& dryRun , "d" , false , "dry run, just print what will be executed" )
28
- flag .BoolVar (& flagVersion , "v" , false , "show version information" )
26
+ flag .BoolVar (& fSelectAll , "a" , false , "select everything by default" )
27
+ flag .BoolVar (& fSelectAllNoConfirm , "A" , false , "select and update everything without confirmation" )
28
+ flag .BoolVar (& fDryRun , "d" , false , "dry run, just print what will be executed" )
29
+ flag .BoolVar (& fVersion , "v" , false , "show version information" )
30
+ flag .BoolVar (& fSort , "s" , false , "sort require lines" )
29
31
}
30
32
31
33
func main () {
32
34
flag .Parse ()
33
35
34
- if flagVersion {
36
+ if fVersion {
35
37
if version != "" {
36
38
fmt .Printf ("version:\t %s\n " , version )
37
39
}
@@ -73,19 +75,25 @@ func updateGoMod(gomodPath string) error {
73
75
gomodPath = filepath .Join (gomodPath , "go.mod" )
74
76
}
75
77
76
- modules , err := parseDirectDeps (gomodPath )
78
+ gomod , err := parseGoMod (gomodPath )
77
79
if err != nil {
78
80
return fmt .Errorf ("parse direct deps: %w" , err )
79
81
}
80
82
83
+ modules := extractDirectDeps (gomod )
84
+
81
85
if len (modules ) == 0 {
82
86
return errors .New ("no direct dependencies found" )
83
87
}
84
88
85
- if selectAllNoConfirm {
89
+ if fSelectAllNoConfirm {
86
90
return runGoGet (gomodPath , modulesToPaths (modules ))
87
91
}
88
92
93
+ if fSort {
94
+ return sortImports (gomodPath , gomod )
95
+ }
96
+
89
97
selected , err := runUI (modules )
90
98
if err != nil {
91
99
return fmt .Errorf ("ui failed: %w" , err )
@@ -98,7 +106,7 @@ func updateGoMod(gomodPath string) error {
98
106
return runGoGet (gomodPath , modulesToPaths (selected ))
99
107
}
100
108
101
- func parseDirectDeps (path string ) ([]module. Version , error ) {
109
+ func parseGoMod (path string ) (* modfile. File , error ) {
102
110
content , err := os .ReadFile (path )
103
111
if err != nil {
104
112
return nil , fmt .Errorf ("read file: %w" , err )
@@ -109,16 +117,20 @@ func parseDirectDeps(path string) ([]module.Version, error) {
109
117
return nil , fmt .Errorf ("parse go.mod: %w" , err )
110
118
}
111
119
120
+ return ast , nil
121
+ }
122
+
123
+ func extractDirectDeps (gomod * modfile.File ) []module.Version {
112
124
var modules []module.Version
113
- for _ , req := range ast .Require {
125
+ for _ , req := range gomod .Require {
114
126
if req .Indirect {
115
127
continue
116
128
}
117
129
118
130
modules = append (modules , req .Mod )
119
131
}
120
132
121
- return modules , nil
133
+ return modules
122
134
}
123
135
124
136
func runUI (modules []module.Version ) ([]module.Version , error ) {
@@ -128,7 +140,7 @@ func runUI(modules []module.Version) ([]module.Version, error) {
128
140
}
129
141
130
142
var findOpts []fzf.FindOption
131
- if selectAll {
143
+ if fSelectAll {
132
144
findOpts = append (findOpts , fzf .WithPreselectAll (true ))
133
145
}
134
146
@@ -151,7 +163,7 @@ func runUI(modules []module.Version) ([]module.Version, error) {
151
163
func runGoGet (path string , selected []string ) error {
152
164
fmt .Println ("go get" , strings .Join (selected , " " ))
153
165
154
- if dryRun {
166
+ if fDryRun {
155
167
return nil
156
168
}
157
169
@@ -176,3 +188,43 @@ func modulesToPaths(modules []module.Version) []string {
176
188
}
177
189
return paths
178
190
}
191
+
192
+ func sortImports (gomodPath string , gomod * modfile.File ) error {
193
+ var direct , indirect []modfile.Require
194
+ for _ , req := range gomod .Require {
195
+ if req .Indirect {
196
+ indirect = append (indirect , * req )
197
+ } else {
198
+ direct = append (direct , * req )
199
+ }
200
+ gomod .DropRequire (req .Mod .Path )
201
+ }
202
+
203
+ for _ , dep := range direct {
204
+ gomod .AddNewRequire (dep .Mod .Path , dep .Mod .Version , false )
205
+ }
206
+ for _ , dep := range indirect {
207
+ gomod .AddNewRequire (dep .Mod .Path , dep .Mod .Version , true )
208
+ }
209
+
210
+ gomod .Cleanup ()
211
+
212
+ gomod .SetRequireSeparateIndirect (gomod .Require )
213
+
214
+ bytes , err := gomod .Format ()
215
+ if err != nil {
216
+ return fmt .Errorf ("format gomod: %w" , err )
217
+ }
218
+
219
+ info , err := os .Stat (gomodPath )
220
+ if err != nil {
221
+ return fmt .Errorf ("stat gomod: %w" , err )
222
+ }
223
+
224
+ err = os .WriteFile (gomodPath , bytes , info .Mode ())
225
+ if err != nil {
226
+ return fmt .Errorf ("write gomod: %w" , err )
227
+ }
228
+
229
+ return nil
230
+ }
0 commit comments