3
3
package main
4
4
5
5
import (
6
+ "encoding/csv"
6
7
"errors"
7
8
"fmt"
8
9
"go/build"
9
10
"os"
10
- "path/filepath"
11
11
"strings"
12
12
13
13
"github.com/spf13/cobra"
14
+ "github.com/spf13/pflag"
14
15
"golang.org/x/tools/go/packages"
15
16
16
17
"github.com/lxc/incus/v6/cmd/generate-database/db"
@@ -64,9 +65,6 @@ func newDbMapper() *cobra.Command {
64
65
}
65
66
66
67
func newDbMapperGenerate () * cobra.Command {
67
- var target string
68
- var build string
69
- var iface bool
70
68
var pkg string
71
69
72
70
cmd := & cobra.Command {
@@ -77,73 +75,74 @@ func newDbMapperGenerate() *cobra.Command {
77
75
return errors .New ("GOPACKAGE environment variable is not set" )
78
76
}
79
77
80
- if os .Getenv ("GOFILE" ) == "" {
81
- return errors .New ("GOFILE environment variable is not set" )
82
- }
83
-
84
- return generate (target , build , iface , pkg )
78
+ return generate (pkg )
85
79
},
86
80
}
87
81
88
82
flags := cmd .Flags ()
89
- flags .BoolVarP (& iface , "interface" , "i" , false , "create interface files" )
90
- flags .StringVarP (& target , "target" , "t" , "-" , "target source file to generate" )
91
- flags .StringVarP (& build , "build" , "b" , "" , "build comment to include" )
92
83
flags .StringVarP (& pkg , "package" , "p" , "" , "Go package where the entity struct is declared" )
93
84
94
85
return cmd
95
86
}
96
87
97
88
const prefix = "//generate-database:mapper "
98
89
99
- func generate (target string , build string , iface bool , pkg string ) error {
100
- err := file .Reset (target , db .Imports , build , iface )
101
- if err != nil {
102
- return err
103
- }
104
-
90
+ func generate (pkg string ) error {
105
91
parsedPkg , err := packageLoad (pkg )
106
92
if err != nil {
107
93
return err
108
94
}
109
95
110
96
registeredSQLStmts := map [string ]string {}
111
97
for _ , goFile := range parsedPkg .CompiledGoFiles {
112
- if filepath .Base (goFile ) != os .Getenv ("GOFILE" ) {
113
- continue
114
- }
115
-
116
98
body , err := os .ReadFile (goFile )
117
99
if err != nil {
118
100
return err
119
101
}
120
102
103
+ // Reset target to stdout
104
+ target := "-"
105
+
121
106
lines := strings .Split (string (body ), "\n " )
122
107
for _ , line := range lines {
123
108
// Lazy matching for prefix, does not consider Go syntax and therefore
124
109
// lines starting with prefix, that are part of e.g. multiline strings
125
110
// match as well. This is highly unlikely to cause false positives.
126
111
if strings .HasPrefix (line , prefix ) {
127
112
line = strings .TrimPrefix (line , prefix )
128
- args := strings .Split (line , " " )
129
113
130
- command := args [ 0 ]
131
- entity := args [ 1 ]
132
- kind := args [ 2 ]
133
- config , err := parseParams ( args [ 3 :] )
114
+ // Use csv parser to properly handle arguments surrounded by double quotes.
115
+ r := csv . NewReader ( strings . NewReader ( line ))
116
+ r . Comma = ' ' // space
117
+ args , err := r . Read ( )
134
118
if err != nil {
135
119
return err
136
120
}
137
121
122
+ if len (args ) == 0 {
123
+ return fmt .Errorf ("command missing" )
124
+ }
125
+
126
+ command := args [0 ]
127
+
138
128
switch command {
129
+ case "target" :
130
+ if len (args ) != 2 {
131
+ return fmt .Errorf ("invalid arguments for command target, one argument for the target filename: %s" , line )
132
+ }
133
+
134
+ target = args [1 ]
135
+ case "reset" :
136
+ err = commandReset (args [1 :], target )
137
+
139
138
case "stmt" :
140
- err = generateStmt ( target , parsedPkg , entity , kind , config , registeredSQLStmts )
139
+ err = commandStmt ( args [ 1 :], target , parsedPkg , registeredSQLStmts )
141
140
142
141
case "method" :
143
- err = generateMethod ( target , iface , parsedPkg , entity , kind , config , registeredSQLStmts )
142
+ err = commandMethod ( args [ 1 :], target , parsedPkg , registeredSQLStmts )
144
143
145
144
default :
146
- err = fmt .Errorf ("undefined command: %s" , command )
145
+ err = fmt .Errorf ("unknown command: %s" , command )
147
146
}
148
147
149
148
if err != nil {
@@ -156,22 +155,83 @@ func generate(target string, build string, iface bool, pkg string) error {
156
155
return nil
157
156
}
158
157
159
- func generateStmt (target string , parsedPkg * packages.Package , entity , kind string , config map [string ]string , registeredSQLStmts map [string ]string ) error {
160
- stmt , err := db .NewStmt (parsedPkg , entity , kind , config , registeredSQLStmts )
158
+ func commandReset (commandLine []string , target string ) error {
159
+ var err error
160
+
161
+ flags := pflag .NewFlagSet ("" , pflag .ContinueOnError )
162
+ iface := flags .BoolP ("interface" , "i" , false , "create interface files" )
163
+ buildComment := flags .StringP ("build" , "b" , "" , "build comment to include" )
164
+
165
+ err = flags .Parse (commandLine )
161
166
if err != nil {
162
167
return err
163
168
}
164
169
165
- return file .Append (entity , target , stmt , false )
170
+ err = file .Reset (target , db .Imports , * buildComment , * iface )
171
+ if err != nil {
172
+ return err
173
+ }
174
+
175
+ return nil
166
176
}
167
177
168
- func generateMethod (target string , iface bool , parsedPkg * packages.Package , entity , kind string , config map [string ]string , registeredSQLStmts map [string ]string ) error {
169
- method , err := db .NewMethod (parsedPkg , entity , kind , config , registeredSQLStmts )
178
+ func commandStmt (commandLine []string , target string , parsedPkg * packages.Package , registeredSQLStmts map [string ]string ) error {
179
+ var err error
180
+
181
+ flags := pflag .NewFlagSet ("" , pflag .ContinueOnError )
182
+ entity := flags .StringP ("entity" , "e" , "" , "database entity to generate the statement for" )
183
+
184
+ err = flags .Parse (commandLine )
185
+ if err != nil {
186
+ return err
187
+ }
188
+
189
+ if len (flags .Args ()) < 1 {
190
+ return fmt .Errorf ("argument <kind> missing for stmt command" )
191
+ }
192
+
193
+ kind := flags .Arg (0 )
194
+ config , err := parseParams (flags .Args ()[1 :])
195
+ if err != nil {
196
+ return err
197
+ }
198
+
199
+ stmt , err := db .NewStmt (parsedPkg , * entity , kind , config , registeredSQLStmts )
200
+ if err != nil {
201
+ return err
202
+ }
203
+
204
+ return file .Append (* entity , target , stmt , false )
205
+ }
206
+
207
+ func commandMethod (commandLine []string , target string , parsedPkg * packages.Package , registeredSQLStmts map [string ]string ) error {
208
+ var err error
209
+
210
+ flags := pflag .NewFlagSet ("" , pflag .ContinueOnError )
211
+ iface := flags .BoolP ("interface" , "i" , false , "create interface files" )
212
+ entity := flags .StringP ("entity" , "e" , "" , "database entity to generate the method for" )
213
+
214
+ err = flags .Parse (commandLine )
215
+ if err != nil {
216
+ return err
217
+ }
218
+
219
+ if len (flags .Args ()) < 1 {
220
+ return fmt .Errorf ("argument <kind> missing for method command" )
221
+ }
222
+
223
+ kind := flags .Arg (0 )
224
+ config , err := parseParams (flags .Args ()[1 :])
225
+ if err != nil {
226
+ return err
227
+ }
228
+
229
+ method , err := db .NewMethod (parsedPkg , * entity , kind , config , registeredSQLStmts )
170
230
if err != nil {
171
231
return err
172
232
}
173
233
174
- return file .Append (entity , target , method , iface )
234
+ return file .Append (* entity , target , method , * iface )
175
235
}
176
236
177
237
func packageLoad (pkg string ) (* packages.Package , error ) {
0 commit comments