From efbb040e3f6ed7da518351080e67d0c68f484539 Mon Sep 17 00:00:00 2001
From: Nick Craig-Wood <nick@craig-wood.com>
Date: Sat, 25 Feb 2017 13:39:16 +0000
Subject: [PATCH] yandex: fix single level directory listing

---
 yandex/api/resource_info_request_helpers.go |  6 +-
 yandex/yandex.go                            | 74 ++++++++++++---------
 2 files changed, 47 insertions(+), 33 deletions(-)

diff --git a/yandex/api/resource_info_request_helpers.go b/yandex/api/resource_info_request_helpers.go
index 941fe066a..8817187ff 100644
--- a/yandex/api/resource_info_request_helpers.go
+++ b/yandex/api/resource_info_request_helpers.go
@@ -14,10 +14,10 @@ func createResourceInfoRequest(c *Client,
 			parameters["sort"] = opt.SortMode.String()
 		}
 		if opt.Limit != nil {
-			parameters["limit"] = opt.Limit
+			parameters["limit"] = *opt.Limit
 		}
 		if opt.Offset != nil {
-			parameters["offset"] = opt.Offset
+			parameters["offset"] = *opt.Offset
 		}
 		if opt.Fields != nil {
 			parameters["fields"] = strings.Join(opt.Fields, ",")
@@ -26,7 +26,7 @@ func createResourceInfoRequest(c *Client,
 			parameters["preview_size"] = opt.PreviewSize.String()
 		}
 		if opt.PreviewCrop != nil {
-			parameters["preview_crop"] = opt.PreviewCrop
+			parameters["preview_crop"] = *opt.PreviewCrop
 		}
 	}
 	return createGetRequest(c, apiPath, parameters)
diff --git a/yandex/yandex.go b/yandex/yandex.go
index 0a9b99e44..cbb8ed6a9 100644
--- a/yandex/yandex.go
+++ b/yandex/yandex.go
@@ -170,32 +170,55 @@ func (f *Fs) setRoot(root string) {
 type listFn func(remote string, item *yandex.ResourceInfoResponse, isDirectory bool) error
 
 // listDir lists this directory only returning objects and directories
-func (f *Fs) listDir(fn listFn) (err error) {
+func (f *Fs) listDir(dir string, fn listFn) (err error) {
 	//request object meta info
 	var opt yandex.ResourceInfoRequestOptions
-	ResourceInfoResponse, err := f.yd.NewResourceInfoRequest(f.diskRoot, opt).Exec()
-	if err != nil {
-		return err
+	root := f.diskRoot
+	if dir != "" {
+		root += dir + "/"
 	}
-	if ResourceInfoResponse.ResourceType == "dir" {
-		//list all subdirs
-		for _, element := range ResourceInfoResponse.Embedded.Items {
-			remote := element.Name
-			switch element.ResourceType {
-			case "dir":
-				err = fn(remote, &element, true)
-				if err != nil {
-					return err
+	var limit uint32 = 1000 // max number of object per request
+	var itemsCount uint32   //number of items per page in response
+	var offset uint32       //for the next page of request
+	opt.Limit = &limit
+	opt.Offset = &offset
+
+	//query each page of list until itemCount is less then limit
+	for {
+		ResourceInfoResponse, err := f.yd.NewResourceInfoRequest(root, opt).Exec()
+		if err != nil {
+			return err
+		}
+		itemsCount = uint32(len(ResourceInfoResponse.Embedded.Items))
+
+		if ResourceInfoResponse.ResourceType == "dir" {
+			//list all subdirs
+			for i, element := range ResourceInfoResponse.Embedded.Items {
+				remote := path.Join(dir, element.Name)
+				fs.Debugf(i, "%q", remote)
+				switch element.ResourceType {
+				case "dir":
+					err = fn(remote, &element, true)
+					if err != nil {
+						return err
+					}
+				case "file":
+					err = fn(remote, &element, false)
+					if err != nil {
+						return err
+					}
+				default:
+					fs.Debugf(f, "Unknown resource type %q", element.ResourceType)
 				}
-			case "file":
-				err = fn(remote, &element, false)
-				if err != nil {
-					return err
-				}
-			default:
-				fs.Debugf(f, "Unknown resource type %q", element.ResourceType)
 			}
 		}
+
+		//offset for the next page of items
+		offset += itemsCount
+		//check if we reached end of list
+		if itemsCount < limit {
+			break
+		}
 	}
 	return nil
 }
@@ -284,22 +307,13 @@ func (f *Fs) List(out fs.ListOpts, dir string) {
 	var err error
 	switch out.Level() {
 	case 1:
-		if dir == "" {
-			err = f.listDir(listItem)
-		} else {
-			err = f.list(dir, listItem)
-		}
+		err = f.listDir(dir, listItem)
 	case fs.MaxLevel:
 		err = f.list(dir, listItem)
 	default:
 		out.SetError(fs.ErrorLevelNotSupported)
 	}
-
 	if err != nil {
-		// FIXME
-		// if err == swift.ContainerNotFound {
-		// 	err = fs.ErrorDirNotFound
-		// }
 		out.SetError(err)
 	}
 }