github.com/goplus/igop@v0.25.0/load/path.go (about) 1 /* 2 * Copyright (c) 2022 The GoPlus Authors (goplus.org). All rights reserved. 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 load 18 19 import ( 20 "bytes" 21 "errors" 22 "fmt" 23 "io/ioutil" 24 "os" 25 "path" 26 "path/filepath" 27 "strings" 28 29 "golang.org/x/mod/modfile" 30 ) 31 32 // GetImportPath get import path from dir. 33 // - lookup go.mod and check modpath+dir+pkgname 34 // - use go list check if BuildMod == "mod". 35 func GetImportPath(pkgName string, dir string) (string, error) { 36 if BuildMod == "mod" { 37 data, err := runGoCommand(dir, "list", "-e", "-mod=mod") 38 if err != nil { 39 return "", err 40 } 41 return string(bytes.TrimSuffix(data, []byte{'\n'})), nil 42 } 43 dir, err := absDir(dir) 44 if err != nil { 45 return "", err 46 } 47 if pkgName == "" || pkgName == "main" { 48 _, pkgName = filepath.Split(dir) 49 } 50 mod, found := findModule(dir) 51 if !found { 52 return pkgName, nil 53 } 54 f, err := ParseModFile(mod) 55 if err != nil { 56 return "", err 57 } 58 root := filepath.Dir(f.Syntax.Name) 59 modPath := f.Module.Mod.Path 60 dir = filepath.ToSlash(dir) 61 root = filepath.ToSlash(root) 62 if dir == root { 63 return modPath, nil 64 } 65 _dir, _ := path.Split(dir[len(root)+1:]) 66 return path.Join(modPath, _dir, pkgName), nil 67 } 68 69 func absDir(dir string) (string, error) { 70 if dir == "" { 71 dir = "." 72 } 73 return filepath.Abs(dir) 74 } 75 76 func findModule(dir string) (file string, found bool) { 77 for dir != "" { 78 file = filepath.Join(dir, "go.mod") 79 if fi, e := os.Lstat(file); e == nil && !fi.IsDir() { 80 found = true 81 return 82 } 83 if dir, file = filepath.Split(strings.TrimRight(dir, "/\\")); file == "" { 84 break 85 } 86 } 87 return 88 } 89 90 // ParseModFile parse go.mod 91 func ParseModFile(file string) (*modfile.File, error) { 92 data, err := ioutil.ReadFile(file) 93 if err != nil { 94 return nil, err 95 } 96 fix := func(path, vers string) (resolved string, err error) { 97 // do nothing 98 return vers, nil 99 } 100 f, err := modfile.Parse(file, data, fix) 101 if err != nil { 102 return nil, fmt.Errorf("parse go.mod error %w", err) 103 } 104 if f.Module == nil { 105 return nil, errors.New("no module declaration in go.mod") 106 } 107 return f, nil 108 }