github.com/go-maxhub/gremlins@v1.0.1-0.20231227222204-b03a6a1e3e09/core/gomodule/gomodule.go (about) 1 /* 2 * Copyright 2022 The Gremlins Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package gomodule 18 19 import ( 20 "bufio" 21 "bytes" 22 "fmt" 23 "os" 24 "path/filepath" 25 ) 26 27 // GoModule represents the current execution context in Gremlins. 28 // 29 // Name is the module name of the Go module being tested by Gremlins. 30 // Root is the root folder of the Go module. 31 // CallingDir is the folder in which Gremlins is running. 32 type GoModule struct { 33 Name string 34 Root string 35 CallingDir string 36 } 37 38 // Init initializes the current module. It finds the module name and the root 39 // of the module, then returns a GoModule struct. 40 func Init(path string) (GoModule, error) { 41 if path == "" { 42 return GoModule{}, fmt.Errorf("path is not set") 43 } 44 mod, root, err := modPkg(path) 45 if err != nil { 46 return GoModule{}, err 47 } 48 path, _ = filepath.Rel(root, path) 49 50 return GoModule{ 51 Name: mod, 52 Root: root, 53 CallingDir: path, 54 }, nil 55 } 56 57 func modPkg(path string) (string, string, error) { 58 root := findModuleRoot(path) 59 file, err := os.Open(root + "/go.mod") 60 defer func(file *os.File) { 61 _ = file.Close() 62 }(file) 63 if err != nil { 64 return "", "", err 65 } 66 r := bufio.NewReader(file) 67 line, _, err := r.ReadLine() 68 if err != nil { 69 return "", "", err 70 } 71 packageName := bytes.TrimPrefix(line, []byte("module ")) 72 73 return string(packageName), root, nil 74 } 75 76 func findModuleRoot(path string) string { 77 // Inspired by how Go itself finds the module root. 78 path = filepath.Clean(path) 79 for { 80 if fi, err := os.Stat(filepath.Join(path, "go.mod")); err == nil && !fi.IsDir() { 81 return path 82 } 83 d := filepath.Dir(path) 84 if d == path { 85 break 86 } 87 path = d 88 } 89 90 return "" 91 }