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
This commit is contained in:
GingerAdonis authored and GitHub committed 2026-10-13 12:14:25 +01:00
1 parent 102ef16e4b
commit 2aea045979
2 files changed
+31

No files matched your search

+2
View File
@@ -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
@@ -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())
}