/
init.go
70 lines (62 loc) · 1.41 KB
/
init.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package modload
import (
"fmt"
"os"
"path/filepath"
)
var (
modRoot string
initialized bool
)
func ModRoot() string {
if !HasModRoot() {
die("cannot find main module; see 'go help modules'")
}
return modRoot
}
func HasModRoot() bool {
if initialized {
return modRoot != ""
}
initialized = true
cwd, err := os.Getwd()
if err != nil {
die(err.Error())
}
for {
modPath := filepath.Join(cwd, "go.mod")
if _, err := os.Stat(modPath); err == nil {
modRoot = cwd
if vendorRoot, ok := findVendorMod(modRoot); ok {
modRoot = vendorRoot
}
return true
} else if cwd[len(cwd)-1] == os.PathSeparator {
return false
}
cwd = filepath.Dir(cwd)
}
}
// findVendorMod will find the module file for the
// project vendoring this dependency if we are inside
// of a vendor directory.
func findVendorMod(cwd string) (string, bool) {
cwd = filepath.Dir(cwd)
// According to its godoc, the return value for `filepath.Dir` will
// only end in a path separator when it's the root directory.
for cwd[len(cwd)-1] != os.PathSeparator {
modPath := filepath.Join(cwd, "go.mod")
if _, err := os.Stat(modPath); err == nil {
vendorPath := filepath.Join(cwd, "vendor")
if st, err := os.Stat(vendorPath); err == nil && st.IsDir() {
return cwd, true
}
}
cwd = filepath.Dir(cwd)
}
return "", false
}
func die(msg string) {
_, _ = fmt.Fprintf(os.Stderr, "modfile: %s\n", msg)
os.Exit(1)
}