walker.go 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. package ftp
  2. import (
  3. "path"
  4. )
  5. // Walker traverses the directory tree of a remote FTP server
  6. type Walker struct {
  7. serverConn *ServerConn
  8. root string
  9. cur *item
  10. stack []*item
  11. descend bool
  12. }
  13. type item struct {
  14. path string
  15. entry *Entry
  16. err error
  17. }
  18. // Next advances the Walker to the next file or directory,
  19. // which will then be available through the Path, Stat, and Err methods.
  20. // It returns false when the walk stops at the end of the tree.
  21. func (w *Walker) Next() bool {
  22. // check if we need to init cur, maybe this should be inside Walk
  23. if w.cur == nil {
  24. w.cur = &item{
  25. path: w.root,
  26. entry: &Entry{
  27. Type: EntryTypeFolder,
  28. },
  29. }
  30. }
  31. if w.descend && w.cur.entry.Type == EntryTypeFolder {
  32. entries, err := w.serverConn.List(w.cur.path)
  33. // an error occurred, drop out and stop walking
  34. if err != nil {
  35. w.cur.err = err
  36. return false
  37. }
  38. for _, entry := range entries {
  39. if entry.Name == "." || entry.Name == ".." {
  40. continue
  41. }
  42. item := &item{
  43. path: path.Join(w.cur.path, entry.Name),
  44. entry: entry,
  45. }
  46. w.stack = append(w.stack, item)
  47. }
  48. }
  49. if len(w.stack) == 0 {
  50. return false
  51. }
  52. // update cur
  53. i := len(w.stack) - 1
  54. w.cur = w.stack[i]
  55. w.stack = w.stack[:i]
  56. // reset SkipDir
  57. w.descend = true
  58. return true
  59. }
  60. // SkipDir tells the Next function to skip the currently processed directory
  61. func (w *Walker) SkipDir() {
  62. w.descend = false
  63. }
  64. // Err returns the error, if any, for the most recent attempt by Next to
  65. // visit a file or a directory. If a directory has an error, the walker
  66. // will not descend in that directory
  67. func (w *Walker) Err() error {
  68. return w.cur.err
  69. }
  70. // Stat returns info for the most recent file or directory
  71. // visited by a call to Next.
  72. func (w *Walker) Stat() *Entry {
  73. return w.cur.entry
  74. }
  75. // Path returns the path to the most recent file or directory
  76. // visited by a call to Next. It contains the argument to Walk
  77. // as a prefix; that is, if Walk is called with "dir", which is
  78. // a directory containing the file "a", Path will return "dir/a".
  79. func (w *Walker) Path() string {
  80. return w.cur.path
  81. }