From 7fe402585e17b70724841d54df1b2f6d251a093b Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Tue, 1 Sep 2026 10:57:48 +0100 Subject: [PATCH] accounting: add NewCheckingTransferNoHistory constructor This creates a checking transfer which is shown in the progress display while it is running but is not kept in the completed transfers history, so it never appears in core/transferred and is not retained in memory after it finishes. This is for repeated bookkeeping operations (eg directory modtime updates) which would otherwise crowd file transfers out of the history. --- fs/accounting/stats.go | 16 +++++++++++++++- fs/accounting/transfer.go | 18 ++++++++++++++---- fs/accounting/transfer_test.go | 19 +++++++++++++++++++ 3 files changed, 48 insertions(+), 5 deletions(-) diff --git a/fs/accounting/stats.go b/fs/accounting/stats.go index a1467b957..bdb92abf7 100644 --- a/fs/accounting/stats.go +++ b/fs/accounting/stats.go @@ -798,6 +798,20 @@ func (s *StatsInfo) NewCheckingTransfer(obj fs.DirEntry, what string) *Transfer return tr } +// NewCheckingTransferNoHistory adds a checking transfer to the stats, +// from the object, which is shown while it is running but is not kept +// in the completed transfers history (so never appears in +// core/transferred). +// +// Use this for repeated bookkeeping operations (eg directory modtime +// updates) which would otherwise crowd file transfers out of the +// history. +func (s *StatsInfo) NewCheckingTransferNoHistory(obj fs.DirEntry, what string) *Transfer { + tr := newCheckingTransferNoHistory(s, obj, what) + s.checking.add(tr) + return tr +} + // DoneChecking removes a check from the stats func (s *StatsInfo) DoneChecking(remote string) { s.checking.del(remote) @@ -831,7 +845,7 @@ func (s *StatsInfo) NewTransfer(obj fs.DirEntry, dstFs fs.Fs) *Transfer { // NewTransferRemoteSize adds a transfer to the stats based on remote and size. func (s *StatsInfo) NewTransferRemoteSize(remote string, size int64, srcFs, dstFs fs.Fs) *Transfer { - tr := newTransferRemoteSize(s, remote, size, false, "", srcFs, dstFs) + tr := newTransferRemoteSize(s, remote, size, false, "", srcFs, dstFs, false) s.transferring.add(tr) s.startAverageLoop() return tr diff --git a/fs/accounting/transfer.go b/fs/accounting/transfer.go index 7703345cb..cb5e4bdab 100644 --- a/fs/accounting/transfer.go +++ b/fs/accounting/transfer.go @@ -71,15 +71,23 @@ type Transfer struct { // newCheckingTransfer instantiates new checking of the object. func newCheckingTransfer(stats *StatsInfo, obj fs.DirEntry, what string) *Transfer { - return newTransferRemoteSize(stats, obj.Remote(), obj.Size(), true, what, nil, nil) + return newTransferRemoteSize(stats, obj.Remote(), obj.Size(), true, what, nil, nil, false) +} + +// newCheckingTransferNoHistory instantiates new checking of the +// object which is not kept in the completed transfers history. +func newCheckingTransferNoHistory(stats *StatsInfo, obj fs.DirEntry, what string) *Transfer { + return newTransferRemoteSize(stats, obj.Remote(), obj.Size(), true, what, nil, nil, true) } // newTransfer instantiates new transfer. func newTransfer(stats *StatsInfo, obj fs.DirEntry, srcFs, dstFs fs.Fs) *Transfer { - return newTransferRemoteSize(stats, obj.Remote(), obj.Size(), false, "", srcFs, dstFs) + return newTransferRemoteSize(stats, obj.Remote(), obj.Size(), false, "", srcFs, dstFs, false) } -func newTransferRemoteSize(stats *StatsInfo, remote string, size int64, checking bool, what string, srcFs, dstFs fs.Fs) *Transfer { +// If noHistory is set the transfer is not kept in the completed +// transfers history after it is done. +func newTransferRemoteSize(stats *StatsInfo, remote string, size int64, checking bool, what string, srcFs, dstFs fs.Fs, noHistory bool) *Transfer { tr := &Transfer{ stats: stats, remote: remote, @@ -90,7 +98,9 @@ func newTransferRemoteSize(stats *StatsInfo, remote string, size int64, checking srcFs: srcFs, dstFs: dstFs, } - stats.AddTransfer(tr) + if !noHistory { + stats.AddTransfer(tr) + } return tr } diff --git a/fs/accounting/transfer_test.go b/fs/accounting/transfer_test.go index a90858ceb..c8b2027b7 100644 --- a/fs/accounting/transfer_test.go +++ b/fs/accounting/transfer_test.go @@ -87,6 +87,25 @@ func TestTransfer(t *testing.T) { }, out) }) + t.Run("NoHistory", func(t *testing.T) { + s := NewStats(ctx) + + // A normal checking transfer is kept in the history + tr := s.NewCheckingTransfer(o, "checking") + tr.Done(ctx, nil) + assert.Equal(t, 1, len(s.Transferred())) + + // A no history checking transfer is shown while running but + // is not kept in the history + tr = s.NewCheckingTransferNoHistory(o, "setting modtime") + assert.Equal(t, 1, s.checking.count()) + assert.Equal(t, 1, len(s.Transferred())) + tr.Done(ctx, nil) + assert.Equal(t, 0, s.checking.count()) + assert.Equal(t, 1, len(s.Transferred())) + assert.Equal(t, int64(2), s.GetChecks()) + }) + t.Run("Snapshot checking transfer", func(t *testing.T) { ctr := newCheckingTransfer(s, o, "checking") snap := ctr.Snapshot()