本站源代码
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.

112 lines
2.5KB

  1. package util
  2. import (
  3. "path/filepath"
  4. "sort"
  5. "strings"
  6. "gopkg.in/src-d/go-billy.v4"
  7. )
  8. // Glob returns the names of all files matching pattern or nil
  9. // if there is no matching file. The syntax of patterns is the same
  10. // as in Match. The pattern may describe hierarchical names such as
  11. // /usr/*/bin/ed (assuming the Separator is '/').
  12. //
  13. // Glob ignores file system errors such as I/O errors reading directories.
  14. // The only possible returned error is ErrBadPattern, when pattern
  15. // is malformed.
  16. //
  17. // Function originally from https://golang.org/src/path/filepath/match_test.go
  18. func Glob(fs billy.Filesystem, pattern string) (matches []string, err error) {
  19. if !hasMeta(pattern) {
  20. if _, err = fs.Lstat(pattern); err != nil {
  21. return nil, nil
  22. }
  23. return []string{pattern}, nil
  24. }
  25. dir, file := filepath.Split(pattern)
  26. // Prevent infinite recursion. See issue 15879.
  27. if dir == pattern {
  28. return nil, filepath.ErrBadPattern
  29. }
  30. var m []string
  31. m, err = Glob(fs, cleanGlobPath(dir))
  32. if err != nil {
  33. return
  34. }
  35. for _, d := range m {
  36. matches, err = glob(fs, d, file, matches)
  37. if err != nil {
  38. return
  39. }
  40. }
  41. return
  42. }
  43. // cleanGlobPath prepares path for glob matching.
  44. func cleanGlobPath(path string) string {
  45. switch path {
  46. case "":
  47. return "."
  48. case string(filepath.Separator):
  49. // do nothing to the path
  50. return path
  51. default:
  52. return path[0 : len(path)-1] // chop off trailing separator
  53. }
  54. }
  55. // glob searches for files matching pattern in the directory dir
  56. // and appends them to matches. If the directory cannot be
  57. // opened, it returns the existing matches. New matches are
  58. // added in lexicographical order.
  59. func glob(fs billy.Filesystem, dir, pattern string, matches []string) (m []string, e error) {
  60. m = matches
  61. fi, err := fs.Stat(dir)
  62. if err != nil {
  63. return
  64. }
  65. if !fi.IsDir() {
  66. return
  67. }
  68. names, _ := readdirnames(fs, dir)
  69. sort.Strings(names)
  70. for _, n := range names {
  71. matched, err := filepath.Match(pattern, n)
  72. if err != nil {
  73. return m, err
  74. }
  75. if matched {
  76. m = append(m, filepath.Join(dir, n))
  77. }
  78. }
  79. return
  80. }
  81. // hasMeta reports whether path contains any of the magic characters
  82. // recognized by Match.
  83. func hasMeta(path string) bool {
  84. // TODO(niemeyer): Should other magic characters be added here?
  85. return strings.ContainsAny(path, "*?[")
  86. }
  87. func readdirnames(fs billy.Filesystem, dir string) ([]string, error) {
  88. files, err := fs.ReadDir(dir)
  89. if err != nil {
  90. return nil, err
  91. }
  92. var names []string
  93. for _, file := range files {
  94. names = append(names, file.Name())
  95. }
  96. return names, nil
  97. }
上海开阖软件有限公司 沪ICP备12045867号-1