file.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. package pathx
  2. import (
  3. "bufio"
  4. "fmt"
  5. "io"
  6. "io/ioutil"
  7. "log"
  8. "os"
  9. "path/filepath"
  10. "strings"
  11. "github.com/logrusorgru/aurora"
  12. "github.com/zeromicro/go-zero/tools/goctl/internal/version"
  13. )
  14. // NL defines a new line.
  15. const (
  16. NL = "\n"
  17. goctlDir = ".goctl"
  18. gitDir = ".git"
  19. autoCompleteDir = ".auto_complete"
  20. cacheDir = "cache"
  21. )
  22. var goctlHome string
  23. // RegisterGoctlHome register goctl home path.
  24. func RegisterGoctlHome(home string) {
  25. goctlHome = home
  26. }
  27. // CreateIfNotExist creates a file if it is not exists.
  28. func CreateIfNotExist(file string) (*os.File, error) {
  29. _, err := os.Stat(file)
  30. if !os.IsNotExist(err) {
  31. return nil, fmt.Errorf("%s already exist", file)
  32. }
  33. return os.Create(file)
  34. }
  35. // RemoveIfExist deletes the specified file if it is exists.
  36. func RemoveIfExist(filename string) error {
  37. if !FileExists(filename) {
  38. return nil
  39. }
  40. return os.Remove(filename)
  41. }
  42. // RemoveOrQuit deletes the specified file if read a permit command from stdin.
  43. func RemoveOrQuit(filename string) error {
  44. if !FileExists(filename) {
  45. return nil
  46. }
  47. fmt.Printf("%s exists, overwrite it?\nEnter to overwrite or Ctrl-C to cancel...",
  48. aurora.BgRed(aurora.Bold(filename)))
  49. bufio.NewReader(os.Stdin).ReadBytes('\n')
  50. return os.Remove(filename)
  51. }
  52. // FileExists returns true if the specified file is exists.
  53. func FileExists(file string) bool {
  54. _, err := os.Stat(file)
  55. return err == nil
  56. }
  57. // FileNameWithoutExt returns a file name without suffix.
  58. func FileNameWithoutExt(file string) string {
  59. return strings.TrimSuffix(file, filepath.Ext(file))
  60. }
  61. // GetGoctlHome returns the path value of the goctl, the default path is ~/.goctl, if the path has
  62. // been set by calling the RegisterGoctlHome method, the user-defined path refers to.
  63. func GetGoctlHome() (home string, err error) {
  64. defer func() {
  65. if err != nil {
  66. return
  67. }
  68. info, err := os.Stat(home)
  69. if err == nil && !info.IsDir() {
  70. os.Rename(home, home+".old")
  71. MkdirIfNotExist(home)
  72. }
  73. }()
  74. if len(goctlHome) != 0 {
  75. home = goctlHome
  76. return
  77. }
  78. home, err = GetDefaultGoctlHome()
  79. return
  80. }
  81. // GetDefaultGoctlHome returns the path value of the goctl home where Join $HOME with .goctl.
  82. func GetDefaultGoctlHome() (string, error) {
  83. home, err := os.UserHomeDir()
  84. if err != nil {
  85. return "", err
  86. }
  87. return filepath.Join(home, goctlDir), nil
  88. }
  89. // GetGitHome returns the git home of goctl.
  90. func GetGitHome() (string, error) {
  91. goctlH, err := GetGoctlHome()
  92. if err != nil {
  93. return "", err
  94. }
  95. return filepath.Join(goctlH, gitDir), nil
  96. }
  97. // GetAutoCompleteHome returns the auto_complete home of goctl.
  98. func GetAutoCompleteHome() (string, error) {
  99. goctlH, err := GetGoctlHome()
  100. if err != nil {
  101. return "", err
  102. }
  103. return filepath.Join(goctlH, autoCompleteDir), nil
  104. }
  105. // GetCacheDir returns the cache dit of goctl.
  106. func GetCacheDir() (string, error) {
  107. goctlH, err := GetGoctlHome()
  108. if err != nil {
  109. return "", err
  110. }
  111. return filepath.Join(goctlH, cacheDir), nil
  112. }
  113. // GetTemplateDir returns the category path value in GoctlHome where could get it by GetGoctlHome.
  114. func GetTemplateDir(category string) (string, error) {
  115. home, err := GetGoctlHome()
  116. if err != nil {
  117. return "", err
  118. }
  119. if home == goctlHome {
  120. // backward compatible, it will be removed in the feature
  121. // backward compatible start.
  122. beforeTemplateDir := filepath.Join(home, version.GetGoctlVersion(), category)
  123. fs, _ := ioutil.ReadDir(beforeTemplateDir)
  124. var hasContent bool
  125. for _, e := range fs {
  126. if e.Size() > 0 {
  127. hasContent = true
  128. }
  129. }
  130. if hasContent {
  131. return beforeTemplateDir, nil
  132. }
  133. // backward compatible end.
  134. return filepath.Join(home, category), nil
  135. }
  136. return filepath.Join(home, version.GetGoctlVersion(), category), nil
  137. }
  138. // InitTemplates creates template files GoctlHome where could get it by GetGoctlHome.
  139. func InitTemplates(category string, templates map[string]string) error {
  140. dir, err := GetTemplateDir(category)
  141. if err != nil {
  142. return err
  143. }
  144. if err := MkdirIfNotExist(dir); err != nil {
  145. return err
  146. }
  147. for k, v := range templates {
  148. if err := createTemplate(filepath.Join(dir, k), v, false); err != nil {
  149. return err
  150. }
  151. }
  152. return nil
  153. }
  154. // CreateTemplate writes template into file even it is exists.
  155. func CreateTemplate(category, name, content string) error {
  156. dir, err := GetTemplateDir(category)
  157. if err != nil {
  158. return err
  159. }
  160. return createTemplate(filepath.Join(dir, name), content, true)
  161. }
  162. // Clean deletes all templates and removes the parent directory.
  163. func Clean(category string) error {
  164. dir, err := GetTemplateDir(category)
  165. if err != nil {
  166. return err
  167. }
  168. return os.RemoveAll(dir)
  169. }
  170. // LoadTemplate gets template content by the specified file.
  171. func LoadTemplate(category, file, builtin string) (string, error) {
  172. dir, err := GetTemplateDir(category)
  173. if err != nil {
  174. return "", err
  175. }
  176. file = filepath.Join(dir, file)
  177. if !FileExists(file) {
  178. return builtin, nil
  179. }
  180. content, err := ioutil.ReadFile(file)
  181. if err != nil {
  182. return "", err
  183. }
  184. return string(content), nil
  185. }
  186. // SameFile compares the between path if the same path,
  187. // it maybe the same path in case case-ignore, such as:
  188. // /Users/go_zero and /Users/Go_zero, as far as we know,
  189. // this case maybe appear on macOS and Windows.
  190. func SameFile(path1, path2 string) (bool, error) {
  191. stat1, err := os.Stat(path1)
  192. if err != nil {
  193. return false, err
  194. }
  195. stat2, err := os.Stat(path2)
  196. if err != nil {
  197. return false, err
  198. }
  199. return os.SameFile(stat1, stat2), nil
  200. }
  201. func createTemplate(file, content string, force bool) error {
  202. if FileExists(file) && !force {
  203. return nil
  204. }
  205. f, err := os.Create(file)
  206. if err != nil {
  207. return err
  208. }
  209. defer f.Close()
  210. _, err = f.WriteString(content)
  211. return err
  212. }
  213. // MustTempDir creates a temporary directory.
  214. func MustTempDir() string {
  215. dir, err := ioutil.TempDir("", "")
  216. if err != nil {
  217. log.Fatalln(err)
  218. }
  219. return dir
  220. }
  221. func Copy(src, dest string) error {
  222. f, err := os.Open(src)
  223. if err != nil {
  224. return err
  225. }
  226. defer f.Close()
  227. dir := filepath.Dir(dest)
  228. err = MkdirIfNotExist(dir)
  229. if err != nil {
  230. return err
  231. }
  232. w, err := os.Create(dest)
  233. if err != nil {
  234. return err
  235. }
  236. w.Chmod(os.ModePerm)
  237. defer w.Close()
  238. _, err = io.Copy(w, f)
  239. return err
  240. }