From 2aea0459790bc642898d5dcff3c494bf220ffc09 Mon Sep 17 00:00:00 2001 From: GingerAdonis <2751672+GingerAdonis@users.noreply.github.com> Date: Tue, 13 Oct 2026 13:14:25 +0200 Subject: [PATCH] onedrive: show the size of directories in listings Directory listings showed every directory with a size of -1, so `rclone lsd` and `operations/list` couldn't say how big a directory was, and finding out meant walking it with `rclone size`. Microsoft Graph already returns each folder's `size` as the total size of its contents, and the backend read it but dropped it. Directories now carry that size, as they already carry the item count. Listing a directory's parent is enough to get the size of all its subdirectories, without listing the subdirectories themselves. OneDrive updates a folder's size in the background, so for a few minutes after a change inside it the size may be out of date. Fixes #7502 --- backend/onedrive/onedrive.go | 2 ++ backend/onedrive/onedrive_internal_test.go | 29 ++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/backend/onedrive/onedrive.go b/backend/onedrive/onedrive.go index e634a495d..d234a5db2 100644 --- a/backend/onedrive/onedrive.go +++ b/backend/onedrive/onedrive.go @@ -1414,6 +1414,8 @@ func (f *Fs) itemToDirEntry(ctx context.Context, dir string, info *api.Item) (en id := info.GetID() f.dirCache.Put(remote, id) d := f.newDir(id, remote) + // OneDrive reports the total size of a folder's contents + d.size = info.GetSize() d.items = folder.ChildCount f.setSystemMetadata(info, d.meta, remote, dirMimeType) entry = d diff --git a/backend/onedrive/onedrive_internal_test.go b/backend/onedrive/onedrive_internal_test.go index 88d8b34f7..9fa964919 100644 --- a/backend/onedrive/onedrive_internal_test.go +++ b/backend/onedrive/onedrive_internal_test.go @@ -18,6 +18,7 @@ import ( "github.com/rclone/rclone/fs/operations" "github.com/rclone/rclone/fstest" "github.com/rclone/rclone/fstest/fstests" + "github.com/rclone/rclone/lib/dircache" "github.com/rclone/rclone/lib/pacer" "github.com/rclone/rclone/lib/random" "github.com/rclone/rclone/lib/rest" @@ -741,3 +742,31 @@ func TestChangeNotifyFollowsNextLink(t *testing.T) { assert.Contains(t, urls[0], "token=tok1") assert.Equal(t, "/nextpage?$skiptoken=abc", urls[1], "the nextLink should be used as-is, without the delta token") } + +// TestListDirectorySize checks that a listed directory carries the size +// OneDrive reports for it, the total size of its contents, instead of -1. +func TestListDirectorySize(t *testing.T) { + ctx := context.Background() + f, _ := newChangeNotifyTestFs(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, "/items/rootid/children", r.URL.Path) + w.Header().Set("Content-Type", "application/json") + _ = json.NewEncoder(w).Encode(api.ListChildrenResponse{ + Value: []api.Item{{ + ID: "dirid", + Name: "photos", + Size: 2646204760, + Folder: &api.FolderFacet{ChildCount: 3}, + }}, + }) + })) + f.dirCache = dircache.New("", "rootid", f) + + entries, err := f.List(ctx, "") + require.NoError(t, err) + require.Len(t, entries, 1) + dir, ok := entries[0].(fs.Directory) + require.True(t, ok, "entry should be a directory") + assert.Equal(t, "photos", dir.Remote()) + assert.Equal(t, int64(2646204760), dir.Size()) + assert.Equal(t, int64(3), dir.Items()) +}