From 9bd5df658a8047054f27fdd964367a53b5702f68 Mon Sep 17 00:00:00 2001 From: dougal Date: Thu, 4 Sep 2025 15:16:43 +0100 Subject: [PATCH] azureblob: add ListP interface - #4788 --- backend/azureblob/azureblob.go | 50 ++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 8 deletions(-) diff --git a/backend/azureblob/azureblob.go b/backend/azureblob/azureblob.go index 71166f3b3..963c11018 100644 --- a/backend/azureblob/azureblob.go +++ b/backend/azureblob/azureblob.go @@ -1338,9 +1338,9 @@ func (f *Fs) containerOK(container string) bool { } // listDir lists a single directory -func (f *Fs) listDir(ctx context.Context, containerName, directory, prefix string, addContainer bool) (entries fs.DirEntries, err error) { +func (f *Fs) listDir(ctx context.Context, containerName, directory, prefix string, addContainer bool, callback func(fs.DirEntry) error) (err error) { if !f.containerOK(containerName) { - return nil, fs.ErrorDirNotFound + return fs.ErrorDirNotFound } err = f.list(ctx, containerName, directory, prefix, addContainer, false, int32(f.opt.ListChunkSize), func(remote string, object *container.BlobItem, isDirectory bool) error { entry, err := f.itemToDirEntry(ctx, remote, object, isDirectory) @@ -1348,16 +1348,16 @@ func (f *Fs) listDir(ctx context.Context, containerName, directory, prefix strin return err } if entry != nil { - entries = append(entries, entry) + return callback(entry) } return nil }) if err != nil { - return nil, err + return err } // container must be present if listing succeeded f.cache.MarkOK(containerName) - return entries, nil + return nil } // listContainers returns all the containers to out @@ -1393,14 +1393,47 @@ func (f *Fs) listContainers(ctx context.Context) (entries fs.DirEntries, err err // This should return ErrDirNotFound if the directory isn't // found. func (f *Fs) List(ctx context.Context, dir string) (entries fs.DirEntries, err error) { + return list.WithListP(ctx, dir, f) +} + +// ListP lists the objects and directories of the Fs starting +// from dir non recursively into out. +// +// dir should be "" to start from the root, and should not +// have trailing slashes. +// +// This should return ErrDirNotFound if the directory isn't +// found. +// +// It should call callback for each tranche of entries read. +// These need not be returned in any particular order. If +// callback returns an error then the listing will stop +// immediately. +func (f *Fs) ListP(ctx context.Context, dir string, callback fs.ListRCallback) error { + list := list.NewHelper(callback) container, directory := f.split(dir) if container == "" { if directory != "" { - return nil, fs.ErrorListBucketRequired + return fs.ErrorListBucketRequired } - return f.listContainers(ctx) + entries, err := f.listContainers(ctx) + if err != nil { + return err + } + for _, entry := range entries { + err = list.Add(entry) + if err != nil { + return err + } + } + } else { + err := f.listDir(ctx, container, directory, f.rootDirectory, f.rootContainer == "", list.Add) + if err != nil { + return err + } + } - return f.listDir(ctx, container, directory, f.rootDirectory, f.rootContainer == "") + return list.Flush() } // ListR lists the objects and directories of the Fs starting @@ -3156,6 +3189,7 @@ var ( _ fs.PutStreamer = &Fs{} _ fs.Purger = &Fs{} _ fs.ListRer = &Fs{} + _ fs.ListPer = &Fs{} _ fs.OpenChunkWriter = &Fs{} _ fs.Object = &Object{} _ fs.MimeTyper = &Object{}