Repository: rclone/rclone
Pull request #8447 (2025-03-13 02:09:18)

build(deps): bump golang.org/x/net from 0.35.0 to 0.36.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.35.0 to 0.36.0.
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/golang/net/commit/85d1d54551b68719346cb9fec24b911da4e452a1"><code>85d1d54</code></a> go.mod: update golang.org/x dependencies</li>
<li><a href="https://github.com/golang/net/commit/cde1dda944dcf6350753df966bb5bda87a544842"><code>cde1dda</code></a> proxy, http/httpproxy: do not mismatch IPv6 zone ids against hosts</li>
<li><a href="https://github.com/golang/net/commit/fe7f0391aa994a401c82d829183c1efab7a64df4"><code>fe7f039</code></a> publicsuffix: spruce up code gen and speed up PublicSuffix</li>
<li><a href="https://github.com/golang/net/commit/459513d1f8abff01b4854c93ff0bff7e87985a0a"><code>459513d</code></a> internal/http3: move more common stream processing to genericConn</li>
<li><a href="https://github.com/golang/net/commit/aad0180cad195ab7bcd14347e7ab51bece53f61d"><code>aad0180</code></a> http2: fix flakiness from t.Log when GOOS=js</li>
<li><a href="https://github.com/golang/net/commit/b73e5746f64471c22097f07593643a743e7cfb0f"><code>b73e574</code></a> http2: don't log expected errors from writing invalid trailers</li>
<li><a href="https://github.com/golang/net/commit/5f45c776a9c4d415cbe67d6c22c06fd704f8c9f1"><code>5f45c77</code></a> internal/http3: make read-data tests usable for server handlers</li>
<li><a href="https://github.com/golang/net/commit/43c2540165a4d1bc9a81e06a86eb1e22ece64145"><code>43c2540</code></a> http2, internal/httpcommon: reject userinfo in :authority</li>
<li><a href="https://github.com/golang/net/commit/1d78a085008d9fedfe3f303591058325f99727d7"><code>1d78a08</code></a> http2, internal/httpcommon: factor out server header logic for h2/h3</li>
<li><a href="https://github.com/golang/net/commit/0d7dc54a591c12b4bd03bcd745024178d03d9218"><code>0d7dc54</code></a> quic: add Conn.ConnectionState</li>
<li>Additional commits viewable in <a href="https://github.com/golang/net/compare/v0.35.0...v0.36.0">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=golang.org/x/net&package-manager=go_modules&previous-version=0.35.0&new-version=0.36.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/rclone/rclone/network/alerts).

</details>


Patch:
diff --git a/fs/accounting/stats.go b/fs/accounting/stats.go
index 88686e6c5..c50ef77b0 100644
--- a/fs/accounting/stats.go
+++ b/fs/accounting/stats.go
@@ -92,7 +92,9 @@ func NewStats(ctx context.Context) *StatsInfo {
 }
 
 // RemoteStats returns stats for rc
-func (s *StatsInfo) RemoteStats() (out rc.Params, err error) {
+//
+// If short is true then the transfers and checkers won't be added.
+func (s *StatsInfo) RemoteStats(short bool) (out rc.Params, err error) {
 	// NB if adding values here - make sure you update the docs in
 	// stats_groups.go
 
@@ -128,10 +130,10 @@ func (s *StatsInfo) RemoteStats() (out rc.Params, err error) {
 	}
 	s.mu.RUnlock()
 
-	if !s.checking.empty() {
+	if !short && !s.checking.empty() {
 		out["checking"] = s.checking.remotes()
 	}
-	if !s.transferring.empty() {
+	if !short && !s.transferring.empty() {
 		out["transferring"] = s.transferring.rcStats(s.inProgress)
 	}
 	if s.errors > 0 {
@@ -561,7 +563,7 @@ func (s *StatsInfo) Transferred() []TransferSnapshot {
 // Log outputs the StatsInfo to the log
 func (s *StatsInfo) Log() {
 	if s.ci.UseJSONLog {
-		out, _ := s.RemoteStats()
+		out, _ := s.RemoteStats(false)
 		fs.LogLevelPrintf(s.ci.StatsLogLevel, nil, "%v%v\n", s, fs.LogValueHide("stats", out))
 	} else {
 		fs.LogLevelPrintf(s.ci.StatsLogLevel, nil, "%v\n", s)
diff --git a/fs/accounting/stats_groups.go b/fs/accounting/stats_groups.go
index 5f8e44d17..13236aa52 100644
--- a/fs/accounting/stats_groups.go
+++ b/fs/accounting/stats_groups.go
@@ -56,11 +56,13 @@ func rcRemoteStats(ctx context.Context, in rc.Params) (rc.Params, error) {
 	if rc.NotErrParamNotFound(err) {
 		return rc.Params{}, err
 	}
+	short, _ := in.GetBool("short")
+
 	if group != "" {
-		return StatsGroup(ctx, group).RemoteStats()
+		return StatsGroup(ctx, group).RemoteStats(short)
 	}
 
-	return groups.sum(ctx).RemoteStats()
+	return groups.sum(ctx).RemoteStats(short)
 }
 
 func init() {
@@ -78,7 +80,8 @@ returned.
 
 Parameters
 
-- group - name of the stats group (string)
+- group - name of the stats group (string, optional)
+- short - if true will not return the transferring and checking arrays (boolean, optional)
 
 Returns the following values:
 
diff --git a/fs/filter/filter.go b/fs/filter/filter.go
index ebe95e37c..e978074d6 100644
--- a/fs/filter/filter.go
+++ b/fs/filter/filter.go
@@ -522,6 +522,12 @@ func (f *Filter) DumpFilters() string {
 	if !f.ModTimeTo.IsZero() {
 		rules = append(rules, fmt.Sprintf("Last-modified date must be equal or less than: %s", f.ModTimeTo.String()))
 	}
+	if f.Opt.MinSize >= 0 {
+		rules = append(rules, fmt.Sprintf("Minimum size is: %s", f.Opt.MinSize.ByteUnit()))
+	}
+	if f.Opt.MaxSize >= 0 {
+		rules = append(rules, fmt.Sprintf("Maximum size is: %s", f.Opt.MaxSize.ByteUnit()))
+	}
 	rules = append(rules, "--- File filter rules ---")
 	for _, rule := range f.fileRules.rules {
 		rules = append(rules, rule.String())
diff --git a/fs/registry.go b/fs/registry.go
index 628a18afe..2df893394 100644
--- a/fs/registry.go
+++ b/fs/registry.go
@@ -259,15 +259,27 @@ func (o *Option) IsDefault() bool {
 // String turns Option into a string
 func (o *Option) String() string {
 	v := o.GetValue()
-	if stringArray, isStringArray := v.([]string); isStringArray {
+	switch x := v.(type) {
+	case []string:
 		// Treat empty string array as empty string
 		// This is to make the default value of the option help nice
-		if len(stringArray) == 0 {
+		if len(x) == 0 {
 			return ""
 		}
 		// Encode string arrays as CSV
 		// The default Go encoding can't be decoded uniquely
-		return CommaSepList(stringArray).String()
+		return CommaSepList(x).String()
+	case SizeSuffix:
+		str := x.String()
+		// Suffix bare numbers with "B" unless they are 0
+		//
+		// This makes sure that fs.SizeSuffix roundtrips through string
+		if len(str) > 0 && str != "0" {
+			if lastDigit := str[len(str)-1]; lastDigit >= '0' && lastDigit <= '9' {
+				str += "B"
+			}
+		}
+		return str
 	}
 	return fmt.Sprint(v)
 }
diff --git a/go.mod b/go.mod
index 0554b4431..093a444e6 100644
--- a/go.mod
+++ b/go.mod
@@ -81,7 +81,7 @@ require (
 	go.etcd.io/bbolt v1.4.0
 	goftp.io/server/v2 v2.0.1
 	golang.org/x/crypto v0.35.0
-	golang.org/x/net v0.35.0
+	golang.org/x/net v0.36.0
 	golang.org/x/oauth2 v0.27.0
 	golang.org/x/sync v0.11.0
 	golang.org/x/sys v0.30.0
diff --git a/go.sum b/go.sum
index 4cb7c8cc8..0fb09b3dd 100644
--- a/go.sum
+++ b/go.sum
@@ -787,8 +787,8 @@ golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
 golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
 golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
 golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
-golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
-golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
+golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA=
+golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=


Test patch:
diff --git a/fs/accounting/stats_groups_test.go b/fs/accounting/stats_groups_test.go
index 4a0cd8628..e0d156672 100644
--- a/fs/accounting/stats_groups_test.go
+++ b/fs/accounting/stats_groups_test.go
@@ -2,6 +2,7 @@ package accounting
 
 import (
 	"context"
+	"encoding/json"
 	"fmt"
 	"runtime"
 	"testing"
@@ -10,6 +11,7 @@ import (
 	"github.com/rclone/rclone/fs"
 	"github.com/rclone/rclone/fs/fserrors"
 	"github.com/rclone/rclone/fs/rc"
+	"github.com/rclone/rclone/fstest/mockobject"
 	"github.com/rclone/rclone/fstest/testy"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
@@ -141,14 +143,35 @@ func TestStatsGroupOperations(t *testing.T) {
 	})
 
 	t.Run("core/stats", func(t *testing.T) {
+		tr := Stats(ctx).NewCheckingTransfer(mockobject.New("core-check"), "deleting")
+		// defer tr.Done(ctx, nil)
+		_ = tr // don't finish the transfer so we don't mess up the other tests
+		tr2 := Stats(ctx).NewTransfer(mockobject.New("core-transfer"), nil)
+		//defer tr2.Done(ctx, nil)
+		_ = tr2 // don't finish the transfer so we don't mess up the other tests
+
 		call := rc.Calls.Get("core/stats")
 		require.NotNil(t, call)
-		gotNoGroup, err := call.Fn(ctx, rc.Params{})
+
+		got, err := call.Fn(ctx, rc.Params{})
 		require.NoError(t, err)
-		gotGroup, err := call.Fn(ctx, rc.Params{"group": "test-group"})
+		assert.Equal(t, int64(42), got["deletes"])
+		data, err := json.Marshal(got["transferring"])
+		require.NoError(t, err)
+		assert.Contains(t, string(data), "core-transfer")
+		data, err = json.Marshal(got["checking"])
+		require.NoError(t, err)
+		assert.Contains(t, string(data), "core-check")
+
+		got, err = call.Fn(ctx, rc.Params{"short": true})
+		require.NoError(t, err)
+		assert.Equal(t, int64(42), got["deletes"])
+		assert.Nil(t, got["transferring"])
+		assert.Nil(t, got["checking"])
+
+		got, err = call.Fn(ctx, rc.Params{"group": "test-group"})
 		require.NoError(t, err)
-		assert.Equal(t, int64(42), gotNoGroup["deletes"])
-		assert.Equal(t, int64(1), gotGroup["deletes"])
+		assert.Equal(t, int64(1), got["deletes"])
 	})
 
 	t.Run("core/transferred", func(t *testing.T) {
diff --git a/fs/accounting/stats_test.go b/fs/accounting/stats_test.go
index a6378d065..6fcc09837 100644
--- a/fs/accounting/stats_test.go
+++ b/fs/accounting/stats_test.go
@@ -265,7 +265,7 @@ func TestRemoteStats(t *testing.T) {
 		}
 		s.AddTransfer(tr1)
 		time.Sleep(time.Millisecond)
-		rs, err := s.RemoteStats()
+		rs, err := s.RemoteStats(false)
 
 		require.NoError(t, err)
 		assert.Equal(t, float64(10), rs["transferTime"])
diff --git a/fs/filter/filter_test.go b/fs/filter/filter_test.go
index 0b5f934da..ef7a1440b 100644
--- a/fs/filter/filter_test.go
+++ b/fs/filter/filter_test.go
@@ -180,7 +180,9 @@ func TestNewFilterFullExceptFilesFromOpt(t *testing.T) {
 	assert.Equal(t, f.Opt.MinSize, mins)
 	assert.Equal(t, f.Opt.MaxSize, maxs)
 	got := f.DumpFilters()
-	want := `--- File filter rules ---
+	want := `Minimum size is: 100 KiB
+Maximum size is: 1000 KiB
+--- File filter rules ---
 + (^|/)include1$
 + (^|/)include2$
 + (^|/)include3$
diff --git a/fs/fs_test.go b/fs/fs_test.go
index e0099e96a..45b16229c 100644
--- a/fs/fs_test.go
+++ b/fs/fs_test.go
@@ -261,6 +261,34 @@ func TestOptionString(t *testing.T) {
 	assert.Equal(t, "true", caseInsensitiveOption.String())
 }
 
+func TestOptionStringStringArray(t *testing.T) {
+	opt := Option{
+		Name:    "string_array",
+		Default: []string(nil),
+	}
+	assert.Equal(t, "", opt.String())
+	opt.Default = []string{}
+	assert.Equal(t, "", opt.String())
+	opt.Default = []string{"a", "b"}
+	assert.Equal(t, "a,b", opt.String())
+	opt.Default = []string{"hello, world!", "goodbye, world!"}
+	assert.Equal(t, `"hello, world!","goodbye, world!"`, opt.String())
+}
+
+func TestOptionStringSizeSuffix(t *testing.T) {
+	opt := Option{
+		Name:    "size_suffix",
+		Default: SizeSuffix(0),
+	}
+	assert.Equal(t, "0", opt.String())
+	opt.Default = SizeSuffix(-1)
+	assert.Equal(t, "off", opt.String())
+	opt.Default = SizeSuffix(100)
+	assert.Equal(t, "100B", opt.String())
+	opt.Default = SizeSuffix(1024)
+	assert.Equal(t, "1Ki", opt.String())
+}
+
 func TestOptionSet(t *testing.T) {
 	o := caseInsensitiveOption
 	assert.Equal(t, true, o.Value)