From 32c00f31797400de492fe8103f41d4809231938c Mon Sep 17 00:00:00 2001 From: Chris Belsole Date: Sat, 18 May 2019 14:33:42 -0400 Subject: [PATCH 1/3] added schema file globbing fixes #631 --- codegen/config/config.go | 31 +++++++++++++++++-- codegen/config/config_test.go | 14 +++++++++ codegen/config/testdata/cfg/glob.yml | 9 ++++++ .../cfg/glob/bar/bar with spaces.graphql | 12 +++++++ .../config/testdata/cfg/glob/foo/foo.graphql | 11 +++++++ codegen/config/testdata/cfg/unwalkable.yml | 9 ++++++ 6 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 codegen/config/testdata/cfg/glob.yml create mode 100644 codegen/config/testdata/cfg/glob/bar/bar with spaces.graphql create mode 100644 codegen/config/testdata/cfg/glob/foo/foo.graphql create mode 100644 codegen/config/testdata/cfg/unwalkable.yml diff --git a/codegen/config/config.go b/codegen/config/config.go index 1725adab0e8..4d642c6140a 100644 --- a/codegen/config/config.go +++ b/codegen/config/config.go @@ -6,6 +6,7 @@ import ( "io/ioutil" "os" "path/filepath" + "regexp" "sort" "strings" @@ -67,9 +68,33 @@ func LoadConfig(filename string) (*Config, error) { preGlobbing := config.SchemaFilename config.SchemaFilename = StringList{} for _, f := range preGlobbing { - matches, err := filepath.Glob(f) - if err != nil { - return nil, errors.Wrapf(err, "failed to glob schema filename %s", f) + var matches []string + + // for ** we want to override default globbing patterns and walk all + // subdirectories to match schema files. + if strings.Contains(f, "**") { + pathParts := strings.SplitN(f, "**", 2) + if err := filepath.Walk(pathParts[0], func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + // make sure paths match files + // ?.*\. + fileRegex := regexp.MustCompile(pathParts[0] + "?.*" + strings.Replace(strings.Replace(pathParts[1], ".", "\\.", -1), "*", ".+", -1)) + if fileRegex.MatchString(path) { + matches = append(matches, path) + } + + return nil + }); err != nil { + return nil, errors.Wrapf(err, "failed to walk schema at root %s", pathParts[0]) + } + } else { + matches, err = filepath.Glob(f) + if err != nil { + return nil, errors.Wrapf(err, "failed to glob schema filename %s", f) + } } for _, m := range matches { diff --git a/codegen/config/config_test.go b/codegen/config/config_test.go index 6ac5257cfdd..1a22c3fda98 100644 --- a/codegen/config/config_test.go +++ b/codegen/config/config_test.go @@ -1,6 +1,7 @@ package config import ( + "fmt" "os" "path/filepath" "testing" @@ -24,6 +25,19 @@ func TestLoadConfig(t *testing.T) { _, err := LoadConfig("testdata/cfg/unknownkeys.yml") require.EqualError(t, err, "unable to parse config: yaml: unmarshal errors:\n line 2: field unknown not found in type config.Config") }) + + t.Run("globbed filenames", func(t *testing.T) { + c, err := LoadConfig("testdata/cfg/glob.yml") + require.NoError(t, err, "") + fmt.Printf("%+v\n", c) + require.Equal(t, c.SchemaFilename[0], "testdata/cfg/glob/bar/bar with spaces.graphql") + require.Equal(t, c.SchemaFilename[1], "testdata/cfg/glob/foo/foo.graphql") + }) + + t.Run("unwalkable path", func(t *testing.T) { + _, err := LoadConfig("testdata/cfg/unwalkable.yml") + require.EqualError(t, err, "failed to walk schema at root not_walkable/: lstat not_walkable/: no such file or directory") + }) } func TestLoadDefaultConfig(t *testing.T) { diff --git a/codegen/config/testdata/cfg/glob.yml b/codegen/config/testdata/cfg/glob.yml new file mode 100644 index 00000000000..87edd2cff56 --- /dev/null +++ b/codegen/config/testdata/cfg/glob.yml @@ -0,0 +1,9 @@ +schema: +- testdata/cfg/glob/**/*.graphql +exec: + filename: generated.go +model: + filename: models_gen.go +resolver: + filename: resolver.go + type: Resolver diff --git a/codegen/config/testdata/cfg/glob/bar/bar with spaces.graphql b/codegen/config/testdata/cfg/glob/bar/bar with spaces.graphql new file mode 100644 index 00000000000..b01bcc433a2 --- /dev/null +++ b/codegen/config/testdata/cfg/glob/bar/bar with spaces.graphql @@ -0,0 +1,12 @@ +type Query { + todos: [Todo!]! +} + +input NewTodo { + text: String! + userId: String! +} + +type Mutation { + createTodo(input: NewTodo!): Todo! +} diff --git a/codegen/config/testdata/cfg/glob/foo/foo.graphql b/codegen/config/testdata/cfg/glob/foo/foo.graphql new file mode 100644 index 00000000000..5f0496c9731 --- /dev/null +++ b/codegen/config/testdata/cfg/glob/foo/foo.graphql @@ -0,0 +1,11 @@ +type Todo { + id: ID! + text: String! + done: Boolean! + user: User! +} + +type User { + id: ID! + name: String! +} diff --git a/codegen/config/testdata/cfg/unwalkable.yml b/codegen/config/testdata/cfg/unwalkable.yml new file mode 100644 index 00000000000..2eac23e2e64 --- /dev/null +++ b/codegen/config/testdata/cfg/unwalkable.yml @@ -0,0 +1,9 @@ +schema: +- not_walkable/**/*.graphql +exec: + filename: generated.go +model: + filename: models_gen.go +resolver: + filename: resolver.go + type: Resolver From 7a2bc437862d53d15c378a2c96f54b4afb00a2ba Mon Sep 17 00:00:00 2001 From: Chris Belsole Date: Sat, 18 May 2019 14:36:09 -0400 Subject: [PATCH 2/3] cleanup --- codegen/config/config.go | 5 ++++- codegen/config/config_test.go | 5 ++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/codegen/config/config.go b/codegen/config/config.go index 4d642c6140a..1139a66ec0b 100644 --- a/codegen/config/config.go +++ b/codegen/config/config.go @@ -81,7 +81,10 @@ func LoadConfig(filename string) (*Config, error) { // make sure paths match files // ?.*\. - fileRegex := regexp.MustCompile(pathParts[0] + "?.*" + strings.Replace(strings.Replace(pathParts[1], ".", "\\.", -1), "*", ".+", -1)) + fileRegex := regexp.MustCompile( + pathParts[0] + + "?.*" + + strings.Replace(strings.Replace(pathParts[1], ".", "\\.", -1), "*", ".+", -1)) if fileRegex.MatchString(path) { matches = append(matches, path) } diff --git a/codegen/config/config_test.go b/codegen/config/config_test.go index 1a22c3fda98..e84f940f9f5 100644 --- a/codegen/config/config_test.go +++ b/codegen/config/config_test.go @@ -1,7 +1,6 @@ package config import ( - "fmt" "os" "path/filepath" "testing" @@ -28,8 +27,8 @@ func TestLoadConfig(t *testing.T) { t.Run("globbed filenames", func(t *testing.T) { c, err := LoadConfig("testdata/cfg/glob.yml") - require.NoError(t, err, "") - fmt.Printf("%+v\n", c) + require.NoError(t, err) + require.Equal(t, c.SchemaFilename[0], "testdata/cfg/glob/bar/bar with spaces.graphql") require.Equal(t, c.SchemaFilename[1], "testdata/cfg/glob/foo/foo.graphql") }) From 57587492931fcf6384e2bfdb3a2c58ef8cb811b1 Mon Sep 17 00:00:00 2001 From: Chris Belsole Date: Sat, 18 May 2019 14:38:48 -0400 Subject: [PATCH 3/3] updated docs --- docs/content/config.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/content/config.md b/docs/content/config.md index 98cb7127e8b..eee5cb60520 100644 --- a/docs/content/config.md +++ b/docs/content/config.md @@ -17,11 +17,15 @@ schema: schema.graphql schema: - schema.graphql - user.graphql - + # Or you can use globs -schema: +schema: - "*.graphql" - + +# Or globs from a root directory +schema: + - "schema/**/*.graphql" + # Let gqlgen know where to put the generated server exec: filename: graph/generated/generated.go