github.com/msoap/go-carpet@v1.10.1-0.20240316220419-b690da179708/mod.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "io" 6 "log" 7 "os" 8 "os/exec" 9 "path" 10 "strings" 11 12 "github.com/msoap/byline" 13 ) 14 15 var goModFilename *string 16 17 func getGoModFilename() string { 18 if goModFilename != nil { 19 return *goModFilename 20 } 21 22 file := "" 23 out, err := exec.Command("go", "env", "GOMOD").Output() 24 if err != nil { 25 log.Printf("failed to load 'go env GOMOD' content: %s", err) 26 goModFilename = &file 27 return "" 28 } 29 30 file = strings.TrimSpace(string(out)) 31 goModFilename = &file 32 33 return file 34 } 35 36 func guessAbsPathInGoMod(relPath string) (string, error) { 37 modFilename := getGoModFilename() 38 if modFilename == "" { 39 return "", errIsNotInGoMod 40 } 41 42 modFile, err := os.Open(modFilename) 43 if err != nil { 44 return "", err 45 } 46 defer func() { 47 if err := modFile.Close(); err != nil { 48 log.Printf("failed to close %s file: %s", modFilename, err) 49 } 50 }() 51 52 moduleName := "" 53 if err := byline.NewReader(modFile).AWKMode(func(_ string, fields []string, vars byline.AWKVars) (string, error) { 54 if vars.NF == 2 && fields[0] == "module" && fields[1] != "" { 55 moduleName = fields[1] 56 return "", io.EOF 57 } 58 59 return "", nil 60 }).Discard(); err != nil { 61 return "", err 62 } 63 if moduleName == "" { 64 return "", errIsNotInGoMod 65 } 66 67 absPath := path.Dir(modFilename) + strings.TrimPrefix(relPath, moduleName) 68 if stat, err := os.Stat(absPath); err != nil { 69 return "", err 70 } else if !stat.Mode().IsRegular() { 71 return "", fmt.Errorf("%s is not regular file", absPath) 72 } 73 74 return absPath, nil 75 }