Add ListDirSorted function to list a directory

* fix error return of readFilesFn also
This commit is contained in:
Nick Craig-Wood 2017-01-24 11:00:05 +00:00
parent 85f05c57d1
commit c3b2b89473
2 changed files with 124 additions and 1 deletions

View file

@ -504,7 +504,72 @@ func readFilesFn(fs Fs, includeAll bool, dir string, add func(Object) error) (er
Debug(o, "Excluded from sync (and deletion)")
}
}
return nil
return list.Error()
}
// DirEntries is a slice of Object or *Dir
type DirEntries []BasicInfo
// Len is part of sort.Interface.
func (ds DirEntries) Len() int {
return len(ds)
}
// Swap is part of sort.Interface.
func (ds DirEntries) Swap(i, j int) {
ds[i], ds[j] = ds[j], ds[i]
}
// Less is part of sort.Interface.
func (ds DirEntries) Less(i, j int) bool {
return ds[i].Remote() < ds[j].Remote()
}
// FIXME can use this in Mount
// ListDirSorted reads Object and *Dir into entries for the given Fs.
//
// dir is the start directory, "" for root
//
// If includeAll is specified all files will be added, otherwise only
// files passing the filter will be added.
//
// Files will be returned in sorted order
func ListDirSorted(fs Fs, includeAll bool, dir string) (entries DirEntries, err error) {
list := NewLister().SetLevel(1)
if !includeAll {
list.SetFilter(Config.Filter)
}
list.Start(fs, dir)
for {
o, dir, err := list.Get()
if err != nil {
return nil, err
} else if o != nil {
// Make sure we don't delete excluded files if not required
if includeAll || Config.Filter.IncludeObject(o) {
entries = append(entries, o)
} else {
Debug(o, "Excluded from sync (and deletion)")
}
} else if dir != nil {
if includeAll || Config.Filter.IncludeDirectory(dir.Remote()) {
entries = append(entries, dir)
} else {
Debug(dir, "Excluded from sync (and deletion)")
}
} else {
// finishd since err, o, dir == nil
break
}
}
err = list.Error()
if err != nil {
return nil, err
}
// sort the directory entries by Remote
sort.Sort(entries)
return entries, nil
}
// Read a map of Object.Remote to Object for the given Fs.

View file

@ -883,3 +883,61 @@ func TestOverlapping(t *testing.T) {
assert.Equal(t, test.expected, actual, what)
}
}
func TestListDirSorted(t *testing.T) {
r := NewRun(t)
defer r.Finalise()
fs.Config.Filter.MaxSize = 10
defer func() {
fs.Config.Filter.MaxSize = -1
}()
r.WriteObject("a.txt", "hello world", t1)
r.WriteObject("zend.txt", "hello", t1)
r.WriteObject("sub dir/hello world", "hello world", t1)
r.WriteObject("sub dir/hello world2", "hello world", t1)
r.WriteObject("sub dir/sub sub dir/hello world3", "hello world", t1)
var items fs.DirEntries
var err error
// Turn the BasicInfo into a name, ending with a / if it is a
// dir
str := func(i int) string {
item := items[i]
name := item.Remote()
switch item.(type) {
case fs.Object:
case *fs.Dir:
name += "/"
default:
t.Fatalf("Unknown type %+v", item)
}
return name
}
items, err = fs.ListDirSorted(r.fremote, true, "")
require.NoError(t, err)
require.Len(t, items, 3)
assert.Equal(t, "a.txt", str(0))
assert.Equal(t, "sub dir/", str(1))
assert.Equal(t, "zend.txt", str(2))
items, err = fs.ListDirSorted(r.fremote, false, "")
require.NoError(t, err)
require.Len(t, items, 2)
assert.Equal(t, "sub dir/", str(0))
assert.Equal(t, "zend.txt", str(1))
items, err = fs.ListDirSorted(r.fremote, true, "sub dir")
require.NoError(t, err)
require.Len(t, items, 3)
assert.Equal(t, "sub dir/hello world", str(0))
assert.Equal(t, "sub dir/hello world2", str(1))
assert.Equal(t, "sub dir/sub sub dir/", str(2))
items, err = fs.ListDirSorted(r.fremote, false, "sub dir")
require.NoError(t, err)
require.Len(t, items, 1)
assert.Equal(t, "sub dir/sub sub dir/", str(0))
}