Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(16)

Unified Diff: service/datastore/datastore.go

Issue 1574353004: GitHub #8: Seed indexes from index.yml (Closed) Base URL: https://github.com/luci/gae@master
Patch Set: path argument in FindAndParseIndexYAML, add a couple of tests Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | service/datastore/datastore_test.go » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: service/datastore/datastore.go
diff --git a/service/datastore/datastore.go b/service/datastore/datastore.go
index 68fae10a88300f0fe0773b21bfb45a09654af4a1..0389ab8914415b197f88abc87911eb05541587b9 100644
--- a/service/datastore/datastore.go
+++ b/service/datastore/datastore.go
@@ -6,9 +6,17 @@ package datastore
import (
"fmt"
+ "io"
+ "io/ioutil"
+ "os"
+ "path/filepath"
"reflect"
+ "runtime"
+ "strings"
"github.com/luci/luci-go/common/errors"
+
+ "gopkg.in/yaml.v2"
)
type datastoreImpl struct {
@@ -348,3 +356,86 @@ func (d *datastoreImpl) DeleteMulti(keys []*Key) (err error) {
func (d *datastoreImpl) Raw() RawInterface {
return d.RawInterface
}
+
+// ParseIndexYAML parses the contents of a index YAML file into a list of
+// IndexDefinitions.
+func ParseIndexYAML(content io.Reader) ([]*IndexDefinition, error) {
+ serialized, err := ioutil.ReadAll(content)
+ if err != nil {
+ return nil, err
+ }
+
+ var m map[string][]*IndexDefinition
+ if err := yaml.Unmarshal(serialized, &m); err != nil {
+ return nil, err
+ }
+
+ if _, ok := m["indexes"]; !ok {
+ return nil, fmt.Errorf("datastore: missing key `indexes`: %v", m)
+ }
+ return m["indexes"], nil
+}
+
+// getCallingTestFilePath looks up the call stack until the specified
+// maxStackDepth and returns the absolute path of the first source filename
+// ending with `_test.go`. If no test file is found, getCallingTestFilePath
+// returns a non-nil error.
+func getCallingTestFilePath(maxStackDepth int) (string, error) {
+ pcs := make([]uintptr, maxStackDepth)
+
+ for _, pc := range pcs[:runtime.Callers(0, pcs)] {
+ path, _ := runtime.FuncForPC(pc - 1).FileLine(pc - 1)
+ if filename := filepath.Base(path); strings.HasSuffix(filename, "_test.go") {
+ return path, nil
+ }
+ }
+
+ return "", fmt.Errorf("datastore: failed to determine source file name")
+}
+
+// FindAndParseIndexYAML walks up from the directory specified by path until it
+// finds a `index.yaml` or `index.yml` file. If an index YAML file
+// is found, it opens and parses the file, and returns all the indexes found.
+// If path is a relative path, it is converted into an absolute path
+// relative to the calling test file. To determine the path of the calling test
+// file, FindAndParseIndexYAML walks upto a maximum of 100 call stack frames
+// looking for a file ending with `_test.go`.
+//
+// FindAndParseIndexYAML returns a non-nil error if the root of the drive is
+// reached without finding an index YAML file, if there was
+// an error reading the found index YAML file, or if the calling test file could
+// not be located in the case of a relative path argument.
+func FindAndParseIndexYAML(path string) ([]*IndexDefinition, error) {
+ var currentDir string
+
+ if filepath.IsAbs(path) {
+ currentDir = path
+ } else {
+ testPath, err := getCallingTestFilePath(100)
+ if err != nil {
+ return nil, err
+ }
+ currentDir = filepath.Join(filepath.Dir(testPath), path)
+ }
+
+ isRoot := func(dir string) bool {
+ parentDir := filepath.Dir(dir)
+ return os.IsPathSeparator(dir[len(dir)-1]) && os.IsPathSeparator(parentDir[len(parentDir)-1])
+ }
+
+ for {
+ for _, filename := range []string{"index.yml", "index.yaml"} {
+ file, err := os.Open(filepath.Join(currentDir, filename))
+ if err == nil {
+ defer file.Close()
+ return ParseIndexYAML(file)
+ }
+ }
+
+ if isRoot(currentDir) {
+ return nil, fmt.Errorf("datastore: failed to find index YAML file")
+ }
+
+ currentDir = filepath.Dir(currentDir)
+ }
+}
« no previous file with comments | « no previous file | service/datastore/datastore_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698