Skip to content

Commit 197ed3b

Browse files
authored
cmd: Allow config file location to be specified (#863)
* cmd: Allow config file location to be specified
1 parent df30bbf commit 197ed3b

File tree

4 files changed

+68
-42
lines changed

4 files changed

+68
-42
lines changed

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ require (
1313
github.com/lib/pq v1.9.0
1414
github.com/pingcap/parser v0.0.0-20201024025010-3b2fb4b41d73
1515
github.com/spf13/cobra v1.1.1
16+
github.com/spf13/pflag v1.0.5
1617
golang.org/x/tools v0.0.0-20191219041853-979b82bfef62 // indirect
1718
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
1819
gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71

internal/cmd/cmd.go

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"path/filepath"
1010

1111
"github.com/spf13/cobra"
12+
"github.com/spf13/pflag"
1213
yaml "gopkg.in/yaml.v3"
1314

1415
"github.com/kyleconroy/sqlc/internal/config"
@@ -17,6 +18,8 @@ import (
1718
// Do runs the command logic.
1819
func Do(args []string, stdin io.Reader, stdout io.Writer, stderr io.Writer) int {
1920
rootCmd := &cobra.Command{Use: "sqlc", SilenceUsage: true}
21+
rootCmd.PersistentFlags().StringP("file", "f", "", "specify an alternate config file (default: sqlc.yaml)")
22+
2023
rootCmd.AddCommand(checkCmd)
2124
rootCmd.AddCommand(genCmd)
2225
rootCmd.AddCommand(initCmd)
@@ -57,14 +60,18 @@ var initCmd = &cobra.Command{
5760
Use: "init",
5861
Short: "Create an empty sqlc.yaml settings file",
5962
RunE: func(cmd *cobra.Command, args []string) error {
60-
if _, err := os.Stat("sqlc.yaml"); !os.IsNotExist(err) {
63+
file := "sqlc.yaml"
64+
if f := cmd.Flag("file"); f != nil {
65+
file = f.Value.String()
66+
}
67+
if _, err := os.Stat(file); !os.IsNotExist(err) {
6168
return nil
6269
}
6370
blob, err := yaml.Marshal(config.V1GenerateSettings{Version: "1"})
6471
if err != nil {
6572
return err
6673
}
67-
return ioutil.WriteFile("sqlc.yaml", blob, 0644)
74+
return ioutil.WriteFile(file, blob, 0644)
6875
},
6976
}
7077

@@ -75,22 +82,39 @@ func ParseEnv() Env {
7582
return Env{}
7683
}
7784

78-
var genCmd = &cobra.Command{
79-
Use: "generate",
80-
Short: "Generate Go code from SQL",
81-
Run: func(cmd *cobra.Command, args []string) {
82-
stderr := cmd.ErrOrStderr()
83-
dir, err := os.Getwd()
85+
func getConfigPath(stderr io.Writer, f *pflag.Flag) (string, string) {
86+
if f != nil {
87+
file := f.Value.String()
88+
if file == "" {
89+
fmt.Fprintln(stderr, "error parsing config: file argument is empty")
90+
os.Exit(1)
91+
}
92+
abspath, err := filepath.Abs(file)
93+
if err != nil {
94+
fmt.Fprintf(stderr, "error parsing config: absolute file path lookup failed: %s\n", err)
95+
os.Exit(1)
96+
}
97+
return filepath.Dir(abspath), filepath.Base(abspath)
98+
} else {
99+
wd, err := os.Getwd()
84100
if err != nil {
85101
fmt.Fprintln(stderr, "error parsing sqlc.json: file does not exist")
86102
os.Exit(1)
87103
}
104+
return wd, ""
105+
}
106+
}
88107

89-
output, err := Generate(ParseEnv(), dir, stderr)
108+
var genCmd = &cobra.Command{
109+
Use: "generate",
110+
Short: "Generate Go code from SQL",
111+
Run: func(cmd *cobra.Command, args []string) {
112+
stderr := cmd.ErrOrStderr()
113+
dir, name := getConfigPath(stderr, cmd.Flag("file"))
114+
output, err := Generate(ParseEnv(), dir, name, stderr)
90115
if err != nil {
91116
os.Exit(1)
92117
}
93-
94118
for filename, source := range output {
95119
os.MkdirAll(filepath.Dir(filename), 0755)
96120
if err := ioutil.WriteFile(filename, []byte(source), 0644); err != nil {
@@ -106,12 +130,8 @@ var checkCmd = &cobra.Command{
106130
Short: "Statically check SQL for syntax and type errors",
107131
RunE: func(cmd *cobra.Command, args []string) error {
108132
stderr := cmd.ErrOrStderr()
109-
dir, err := os.Getwd()
110-
if err != nil {
111-
fmt.Fprintln(stderr, "error parsing sqlc.json: file does not exist")
112-
os.Exit(1)
113-
}
114-
if _, err := Generate(Env{}, dir, stderr); err != nil {
133+
dir, name := getConfigPath(stderr, cmd.Flag("file"))
134+
if _, err := Generate(Env{}, dir, name, stderr); err != nil {
115135
os.Exit(1)
116136
}
117137
return nil

internal/cmd/generate.go

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -44,34 +44,39 @@ type outPair struct {
4444
config.SQL
4545
}
4646

47-
func Generate(e Env, dir string, stderr io.Writer) (map[string]string, error) {
48-
var yamlMissing, jsonMissing bool
49-
yamlPath := filepath.Join(dir, "sqlc.yaml")
50-
jsonPath := filepath.Join(dir, "sqlc.json")
47+
func Generate(e Env, dir, filename string, stderr io.Writer) (map[string]string, error) {
48+
configPath := ""
49+
if filename != "" {
50+
configPath = filepath.Join(dir, filename)
51+
} else {
52+
var yamlMissing, jsonMissing bool
53+
yamlPath := filepath.Join(dir, "sqlc.yaml")
54+
jsonPath := filepath.Join(dir, "sqlc.json")
55+
56+
if _, err := os.Stat(yamlPath); os.IsNotExist(err) {
57+
yamlMissing = true
58+
}
59+
if _, err := os.Stat(jsonPath); os.IsNotExist(err) {
60+
jsonMissing = true
61+
}
5162

52-
if _, err := os.Stat(yamlPath); os.IsNotExist(err) {
53-
yamlMissing = true
54-
}
55-
if _, err := os.Stat(jsonPath); os.IsNotExist(err) {
56-
jsonMissing = true
57-
}
63+
if yamlMissing && jsonMissing {
64+
fmt.Fprintln(stderr, "error parsing sqlc.json: file does not exist")
65+
return nil, errors.New("config file missing")
66+
}
5867

59-
if yamlMissing && jsonMissing {
60-
fmt.Fprintln(stderr, "error parsing sqlc.json: file does not exist")
61-
return nil, errors.New("config file missing")
62-
}
68+
if !yamlMissing && !jsonMissing {
69+
fmt.Fprintln(stderr, "error: both sqlc.json and sqlc.yaml files present")
70+
return nil, errors.New("sqlc.json and sqlc.yaml present")
71+
}
6372

64-
if !yamlMissing && !jsonMissing {
65-
fmt.Fprintln(stderr, "error: both sqlc.json and sqlc.yaml files present")
66-
return nil, errors.New("sqlc.json and sqlc.yaml present")
73+
configPath = yamlPath
74+
if yamlMissing {
75+
configPath = jsonPath
76+
}
6777
}
6878

69-
configPath := yamlPath
70-
if yamlMissing {
71-
configPath = jsonPath
72-
}
7379
base := filepath.Base(configPath)
74-
7580
blob, err := ioutil.ReadFile(configPath)
7681
if err != nil {
7782
fmt.Fprintf(stderr, "error parsing %s: file does not exist\n", base)

internal/endtoend/endtoend_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ func TestExamples(t *testing.T) {
3535
t.Parallel()
3636
path := filepath.Join(examples, tc)
3737
var stderr bytes.Buffer
38-
output, err := cmd.Generate(cmd.Env{}, path, &stderr)
38+
output, err := cmd.Generate(cmd.Env{}, path, "", &stderr)
3939
if err != nil {
4040
t.Fatalf("sqlc generate failed: %s", stderr.String())
4141
}
@@ -62,7 +62,7 @@ func BenchmarkExamples(b *testing.B) {
6262
path := filepath.Join(examples, tc)
6363
for i := 0; i < b.N; i++ {
6464
var stderr bytes.Buffer
65-
cmd.Generate(cmd.Env{}, path, &stderr)
65+
cmd.Generate(cmd.Env{}, path, "", &stderr)
6666
}
6767
})
6868
}
@@ -91,7 +91,7 @@ func TestReplay(t *testing.T) {
9191
path, _ := filepath.Abs(tc)
9292
var stderr bytes.Buffer
9393
expected := expectedStderr(t, path)
94-
output, err := cmd.Generate(cmd.Env{}, path, &stderr)
94+
output, err := cmd.Generate(cmd.Env{}, path, "", &stderr)
9595
if len(expected) == 0 && err != nil {
9696
t.Fatalf("sqlc generate failed: %s", stderr.String())
9797
}
@@ -184,7 +184,7 @@ func BenchmarkReplay(b *testing.B) {
184184
path, _ := filepath.Abs(tc)
185185
for i := 0; i < b.N; i++ {
186186
var stderr bytes.Buffer
187-
cmd.Generate(cmd.Env{}, path, &stderr)
187+
cmd.Generate(cmd.Env{}, path, "", &stderr)
188188
}
189189
})
190190
}

0 commit comments

Comments
 (0)