Codebase list golang-github-jlaffaye-ftp / HEAD walker.go
HEAD

Tree @HEAD (Download .tar.gz)

walker.go @HEAD

e6e290c
 
 
3b6697e
e6e290c
 
 
 
 
 
3b6697e
 
e6e290c
 
 
 
 
3b6697e
e6e290c
 
 
74a8c4b
e6e290c
 
74a8c4b
06706f2
3b6697e
 
06706f2
 
 
 
3b6697e
 
 
06706f2
 
3b6697e
52feea7
06706f2
 
3b6697e
 
 
06706f2
 
3b6697e
 
 
 
 
 
e6e290c
3b6697e
 
e6e290c
 
 
 
 
 
3b6697e
06706f2
e6e290c
 
 
06706f2
 
e6e290c
3b6697e
e6e290c
 
 
ee119b0
e6e290c
 
 
 
ee119b0
 
 
e6e290c
 
 
 
 
f82be3d
3b6697e
e6e290c
 
 
 
74a8c4b
e6e290c
 
 
 
 
package ftp

import (
	"path"
)

//Walker traverses the directory tree of a remote FTP server
type Walker struct {
	serverConn *ServerConn
	root       string
	cur        *item
	stack      []*item
	descend    bool
}

type item struct {
	path  string
	entry *Entry
	err   error
}

// Next advances the Walker to the next file or directory,
// which will then be available through the Path, Stat, and Err methods.
// It returns false when the walk stops at the end of the tree.
func (w *Walker) Next() bool {
	// check if we need to init cur, maybe this should be inside Walk
	if w.cur == nil {
		w.cur = &item{
			path: w.root,
			entry: &Entry{
				Type: EntryTypeFolder,
			},
		}
	}

	if w.descend && w.cur.entry.Type == EntryTypeFolder {
		entries, err := w.serverConn.List(w.cur.path)

		// an error occurred, drop out and stop walking
		if err != nil {
			w.cur.err = err
			return false
		}

		for _, entry := range entries {
			if entry.Name == "." || entry.Name == ".." {
				continue
			}

			item := &item{
				path:  path.Join(w.cur.path, entry.Name),
				entry: entry,
			}

			w.stack = append(w.stack, item)
		}
	}

	if len(w.stack) == 0 {
		return false
	}

	// update cur
	i := len(w.stack) - 1
	w.cur = w.stack[i]
	w.stack = w.stack[:i]

	// reset SkipDir
	w.descend = true

	return true
}

// SkipDir tells the Next function to skip the currently processed directory
func (w *Walker) SkipDir() {
	w.descend = false
}

// Err returns the error, if any, for the most recent attempt by Next to
// visit a file or a directory. If a directory has an error, the walker
// will not descend in that directory
func (w *Walker) Err() error {
	return w.cur.err
}

// Stat returns info for the most recent file or directory
// visited by a call to Next.
func (w *Walker) Stat() *Entry {
	return w.cur.entry
}

// Path returns the path to the most recent file or directory
// visited by a call to Next. It contains the argument to Walk
// as a prefix; that is, if Walk is called with "dir", which is
// a directory containing the file "a", Path will return "dir/a".
func (w *Walker) Path() string {
	return w.cur.path
}