From 98778b85e01c13d7ede8c76e35c8c954fb379ec1 Mon Sep 17 00:00:00 2001 From: Stefan Majewsky Date: Thu, 3 May 2018 16:09:23 +0200 Subject: add support for pseudo-directories to ObjectIterator --- object_iterator.go | 43 ++++++++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 11 deletions(-) (limited to 'object_iterator.go') diff --git a/object_iterator.go b/object_iterator.go index 3fb5563..6231292 100644 --- a/object_iterator.go +++ b/object_iterator.go @@ -33,6 +33,11 @@ type ObjectInfo struct { ContentType string Etag string LastModified time.Time + //If the ObjectInfo refers to an actual object, then SubDirectory is empty. + //If the ObjectInfo refers to a pseudo-directory, then SubDirectory contains + //the path of the pseudo-directory and all other fields are nil/zero/empty. + //Pseudo-directories will only be reported for ObjectIterator.Delimiter != "". + SubDirectory string } //ObjectIterator iterates over the objects in a container. It is typically @@ -60,16 +65,22 @@ type ObjectInfo struct { //Use the "Detailed" methods only when you use the extra metadata in struct //ObjectInfo; detailed GET requests are more expensive than simple ones that //return only object names. +// +//Note that, when Delimiter is set, instances of *Object that you receive from +//the iterator may refer to a pseudo-directory instead of an actual object, in +//which case Exists() will return false. type ObjectIterator struct { Container *Container //When Prefix is set, only objects whose name starts with this string are //returned. Prefix string + //When Delimiter is set, objects whose name contains this string (after the + //prefix, if any) will be condensed into pseudo-directories in the result. + //See documentation for Swift for details. + Delimiter string //Options may contain additional headers and query parameters for the GET request. Options *RequestOptions - //TODO: Delimiter field (and check if other stuff is missing) - base *iteratorBase } @@ -107,11 +118,14 @@ func (i *ObjectIterator) NextPageDetailed(limit int) ([]ObjectInfo, error) { b := i.getBase() var document []struct { + //either all of this: SizeBytes uint64 `json:"bytes"` ContentType string `json:"content_type"` Etag string `json:"hash"` LastModifiedStr string `json:"last_modified"` Name string `json:"name"` + //or just this: + Subdir string `json:"subdir"` } err := b.nextPageDetailed(limit, &document) if err != nil { @@ -123,19 +137,26 @@ func (i *ObjectIterator) NextPageDetailed(limit int) ([]ObjectInfo, error) { } result := make([]ObjectInfo, len(document)) + marker := "" for idx, data := range document { - result[idx].Object = i.Container.Object(data.Name) - result[idx].ContentType = data.ContentType - result[idx].Etag = data.Etag - result[idx].SizeBytes = data.SizeBytes - result[idx].LastModified, err = time.Parse(time.RFC3339Nano, data.LastModifiedStr+"Z") - if err != nil { - //this error is sufficiently obscure that we don't need to expose a type for it - return nil, fmt.Errorf("Bad field objects[%d].last_modified: %s", idx, err.Error()) + if data.Subdir == "" { + marker = data.Name + result[idx].Object = i.Container.Object(data.Name) + result[idx].ContentType = data.ContentType + result[idx].Etag = data.Etag + result[idx].SizeBytes = data.SizeBytes + result[idx].LastModified, err = time.Parse(time.RFC3339Nano, data.LastModifiedStr+"Z") + if err != nil { + //this error is sufficiently obscure that we don't need to expose a type for it + return nil, fmt.Errorf("Bad field objects[%d].last_modified: %s", idx, err.Error()) + } + } else { + marker = data.Subdir + result[idx].SubDirectory = data.Subdir } } - b.setMarker(result[len(result)-1].Object.Name()) + b.setMarker(marker) return result, nil } -- cgit v1.2.3