storage: enforce sorted traversal during Walk
Signed-off-by: Stephen J Day <stephen.day@docker.com>
This commit is contained in:
parent
6ad10796ef
commit
5d576bc0cd
2 changed files with 14 additions and 0 deletions
|
@ -3,6 +3,7 @@ package storage
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
|
||||||
"github.com/docker/distribution/context"
|
"github.com/docker/distribution/context"
|
||||||
storageDriver "github.com/docker/distribution/registry/storage/driver"
|
storageDriver "github.com/docker/distribution/registry/storage/driver"
|
||||||
|
@ -26,7 +27,12 @@ func Walk(ctx context.Context, driver storageDriver.StorageDriver, from string,
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
sort.Stable(sort.StringSlice(children))
|
||||||
for _, child := range children {
|
for _, child := range children {
|
||||||
|
// TODO(stevvooe): Calling driver.Stat for every entry is quite
|
||||||
|
// expensive when running against backends with a slow Stat
|
||||||
|
// implementation, such as s3. This is very likely a serious
|
||||||
|
// performance bottleneck.
|
||||||
fileInfo, err := driver.Stat(ctx, child)
|
fileInfo, err := driver.Stat(ctx, child)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -2,6 +2,7 @@ package storage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"sort"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/docker/distribution/context"
|
"github.com/docker/distribution/context"
|
||||||
|
@ -73,6 +74,7 @@ func TestWalkErrors(t *testing.T) {
|
||||||
|
|
||||||
func TestWalk(t *testing.T) {
|
func TestWalk(t *testing.T) {
|
||||||
d, expected, ctx := testFS(t)
|
d, expected, ctx := testFS(t)
|
||||||
|
var traversed []string
|
||||||
err := Walk(ctx, d, "/", func(fileInfo driver.FileInfo) error {
|
err := Walk(ctx, d, "/", func(fileInfo driver.FileInfo) error {
|
||||||
filePath := fileInfo.Path()
|
filePath := fileInfo.Path()
|
||||||
filetype, ok := expected[filePath]
|
filetype, ok := expected[filePath]
|
||||||
|
@ -90,11 +92,17 @@ func TestWalk(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete(expected, filePath)
|
delete(expected, filePath)
|
||||||
|
traversed = append(traversed, filePath)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if len(expected) > 0 {
|
if len(expected) > 0 {
|
||||||
t.Errorf("Missed files in walk: %q", expected)
|
t.Errorf("Missed files in walk: %q", expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !sort.StringsAreSorted(traversed) {
|
||||||
|
t.Errorf("result should be sorted: %v", traversed)
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf(err.Error())
|
t.Fatalf(err.Error())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue