You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

9 年之前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. package fs
  2. import (
  3. "bytes"
  4. "fmt"
  5. "io"
  6. "os"
  7. "os/exec"
  8. "path"
  9. "path/filepath"
  10. "regexp"
  11. "runtime"
  12. "strings"
  13. )
  14. // Getcd returns absolute path of the caller.
  15. func Getcd(skip int) string {
  16. if dir := Geted(); strings.HasPrefix(dir, os.TempDir()) {
  17. pc, _, _, _ := runtime.Caller(skip + 1)
  18. function := runtime.FuncForPC(pc)
  19. filename, _ := function.FileLine(0)
  20. return path.Dir(filename)
  21. } else {
  22. return dir
  23. }
  24. }
  25. // Geted returns an absolute path to the executable.
  26. func Geted() string {
  27. if dir, err := filepath.Abs(filepath.Dir(os.Args[0])); err == nil {
  28. return dir
  29. } else {
  30. panic("Failed to retrieve executable directory")
  31. }
  32. }
  33. // Getwd returns a absolute path of the current directory.
  34. func Getwd() string {
  35. if cwd, err := os.Getwd(); err == nil {
  36. cwd, _ = filepath.Abs(cwd)
  37. return cwd
  38. } else {
  39. panic("Failed to retrieve current working directory")
  40. }
  41. }
  42. // Abs finds the absolute path for the given path.
  43. // Supported Formats:
  44. // * empty path => current working directory.
  45. // * '.', '..' & '~'
  46. // *NOTE* Abs does NOT check the existence of the path.
  47. func Abs(path string) string {
  48. var abs string
  49. cwd, _ := os.Getwd()
  50. if path == "" || path == "." {
  51. abs = cwd
  52. } else if path == ".." {
  53. abs = filepath.Join(cwd, path)
  54. } else if strings.HasPrefix(path, "~/") {
  55. abs = filepath.Join(UserDir(), path[2:])
  56. } else if strings.HasPrefix(path, "./") {
  57. abs = filepath.Join(cwd, path[2:])
  58. } else if strings.HasPrefix(path, "../") {
  59. abs = filepath.Join(cwd, "..", path[2:])
  60. } else {
  61. return path
  62. }
  63. return abs
  64. }
  65. // Copy recursively copies files/(sub)directoires into the given path.
  66. // *NOTE* It uses platform's native copy commands (windows: copy, *nix: rsync).
  67. func Copy(src, dst string) (err error) {
  68. var cmd *exec.Cmd
  69. src, dst = Abs(src), Abs(dst)
  70. // Determine the command we need to use.
  71. if runtime.GOOS == "windows" {
  72. // *NOTE* Not sure this will work correctly, we don't have Windows to test.
  73. if IsFile(src) {
  74. cmd = exec.Command("copy", src, dst)
  75. } else {
  76. cmd = exec.Command("xcopy", src, dst, "/S /E")
  77. }
  78. } else {
  79. cmd = exec.Command("rsync", "-a", src, dst)
  80. }
  81. if stdout, err := cmd.StdoutPipe(); err == nil {
  82. if stderr, err := cmd.StderrPipe(); err == nil {
  83. // Start capturing the stdout/err.
  84. err = cmd.Start()
  85. io.Copy(os.Stdout, stdout)
  86. buffer := new(bytes.Buffer)
  87. buffer.ReadFrom(stderr)
  88. cmd.Wait()
  89. if cmd.ProcessState.String() != "exit status 0" {
  90. err = fmt.Errorf("\t%s\n", buffer.String())
  91. }
  92. }
  93. }
  94. return
  95. }
  96. // Exists check if the given path exists.
  97. func Exists(path string) bool {
  98. if _, err := os.Stat(path); err != nil {
  99. if os.IsNotExist(err) {
  100. return false
  101. }
  102. }
  103. return true
  104. }
  105. // Find matches files with regular expression pattern under the given root.
  106. func Find(root string, pattern *regexp.Regexp) (paths []string) {
  107. if Exists(root) {
  108. filepath.Walk(root, func(path string, info os.FileInfo, e error) error {
  109. if pattern.MatchString(path) {
  110. paths = append(paths, info.Name())
  111. }
  112. return e
  113. })
  114. }
  115. return
  116. }
  117. // Grep searches text files via regular expression under the given path,
  118. // paths of the files contain matched line(s) will be returned.
  119. func Grep(root string, pattern *regexp.Regexp) (paths []string) {
  120. panic(fmt.Errorf("Not Implemented"))
  121. }
  122. // Glob recursively finds the names of all files matching pattern under the given path.
  123. func Glob(path string, pattern string) (matches []string, err error) {
  124. err = filepath.Walk(path, func(path string, info os.FileInfo, e error) error {
  125. if e == nil {
  126. if info.IsDir() {
  127. if filenames, e := filepath.Glob(filepath.Join(path, pattern)); e == nil {
  128. matches = append(matches, filenames...)
  129. }
  130. }
  131. }
  132. return e
  133. })
  134. return
  135. }
  136. // IsDir checks if the given path is a directory.
  137. func IsDir(path string) bool {
  138. src, err := os.Stat(path)
  139. if os.IsNotExist(err) {
  140. return false
  141. }
  142. return src.IsDir()
  143. }
  144. // IsFile checks if the given path is a file.
  145. func IsFile(path string) bool {
  146. src, err := os.Stat(path)
  147. if os.IsNotExist(err) {
  148. return false
  149. }
  150. return !src.IsDir()
  151. }
  152. // UserDir finds base path of current system user.
  153. func UserDir() string {
  154. if runtime.GOOS == "windows" {
  155. home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
  156. if home == "" {
  157. home = os.Getenv("USERPROFILE")
  158. }
  159. return home
  160. }
  161. return os.Getenv("HOME")
  162. }