path.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. package util
  2. import (
  3. "fmt"
  4. "os"
  5. "path"
  6. "path/filepath"
  7. "runtime"
  8. "strings"
  9. "github.com/tal-tech/go-zero/tools/goctl/vars"
  10. )
  11. const (
  12. pkgSep = "/"
  13. goModeIdentifier = "go.mod"
  14. )
  15. // JoinPackages calls strings.Join and returns
  16. func JoinPackages(pkgs ...string) string {
  17. return strings.Join(pkgs, pkgSep)
  18. }
  19. // MkdirIfNotExist makes directories if the input path is not exists
  20. func MkdirIfNotExist(dir string) error {
  21. if len(dir) == 0 {
  22. return nil
  23. }
  24. if _, err := os.Stat(dir); os.IsNotExist(err) {
  25. return os.MkdirAll(dir, os.ModePerm)
  26. }
  27. return nil
  28. }
  29. // PathFromGoSrc returns the path without slash where has been trim the prefix $GOPATH
  30. func PathFromGoSrc() (string, error) {
  31. dir, err := os.Getwd()
  32. if err != nil {
  33. return "", err
  34. }
  35. gopath := os.Getenv("GOPATH")
  36. parent := path.Join(gopath, "src", vars.ProjectName)
  37. pos := strings.Index(dir, parent)
  38. if pos < 0 {
  39. return "", fmt.Errorf("%s is not in GOPATH", dir)
  40. }
  41. // skip slash
  42. return dir[len(parent)+1:], nil
  43. }
  44. // FindGoModPath returns the path in project where has file go.mod, it maybe return empty string if
  45. // there is no go.mod file in project
  46. func FindGoModPath(dir string) (string, bool) {
  47. absDir, err := filepath.Abs(dir)
  48. if err != nil {
  49. return "", false
  50. }
  51. absDir = strings.ReplaceAll(absDir, `\`, `/`)
  52. var rootPath string
  53. tempPath := absDir
  54. hasGoMod := false
  55. for {
  56. if FileExists(filepath.Join(tempPath, goModeIdentifier)) {
  57. rootPath = strings.TrimPrefix(absDir[len(tempPath):], "/")
  58. hasGoMod = true
  59. break
  60. }
  61. if tempPath == filepath.Dir(tempPath) {
  62. break
  63. }
  64. tempPath = filepath.Dir(tempPath)
  65. if tempPath == string(filepath.Separator) {
  66. break
  67. }
  68. }
  69. if hasGoMod {
  70. return rootPath, true
  71. }
  72. return "", false
  73. }
  74. // FindProjectPath returns the parent directory where has file go.mod in project
  75. func FindProjectPath(loc string) (string, bool) {
  76. var dir string
  77. if strings.IndexByte(loc, '/') == 0 {
  78. dir = loc
  79. } else {
  80. wd, err := os.Getwd()
  81. if err != nil {
  82. return "", false
  83. }
  84. dir = filepath.Join(wd, loc)
  85. }
  86. for {
  87. if FileExists(filepath.Join(dir, goModeIdentifier)) {
  88. return dir, true
  89. }
  90. dir = filepath.Dir(dir)
  91. if dir == "/" {
  92. break
  93. }
  94. }
  95. return "", false
  96. }
  97. // ReadLink returns the destination of the named symbolic link recursively.
  98. func ReadLink(name string) (string, error) {
  99. goos := runtime.GOOS
  100. switch goos {
  101. case vars.OsWindows:
  102. return name, nil
  103. }
  104. name, err := filepath.Abs(name)
  105. if err != nil {
  106. return "", err
  107. }
  108. if _, err := os.Lstat(name); err != nil {
  109. return name, nil
  110. }
  111. // uncheck condition: ignore file path /var, maybe be temporary file path
  112. if name == "/" || name == "/var" {
  113. return name, nil
  114. }
  115. isLink, err := isLink(name)
  116. if err != nil {
  117. return "", err
  118. }
  119. if !isLink {
  120. dir, base := filepath.Split(name)
  121. dir = filepath.Clean(dir)
  122. dir, err := ReadLink(dir)
  123. if err != nil {
  124. return "", err
  125. }
  126. return filepath.Join(dir, base), nil
  127. }
  128. link, err := os.Readlink(name)
  129. if err != nil {
  130. return "", err
  131. }
  132. dir, base := filepath.Split(link)
  133. dir = filepath.Dir(dir)
  134. dir, err = ReadLink(dir)
  135. if err != nil {
  136. return "", err
  137. }
  138. return filepath.Join(dir, base), nil
  139. }
  140. func isLink(name string) (bool, error) {
  141. fi, err := os.Lstat(name)
  142. if err != nil {
  143. return false, err
  144. }
  145. return fi.Mode()&os.ModeSymlink != 0, nil
  146. }