Compare commits
7 Commits
v2.0.0-rc.17
...
v1.29.7
| Author | SHA1 | Date | |
|---|---|---|---|
| 40660c5fb7 | |||
| d940d094a1 | |||
| 9d67727989 | |||
| 6f51700a7f | |||
| 598915193a | |||
| 905e5ec07f | |||
| 4075b886d0 |
@@ -0,0 +1,23 @@
|
||||
version: 1
|
||||
labels:
|
||||
|
||||
- label: enhancement
|
||||
title: ^feat\b
|
||||
|
||||
- label: bug
|
||||
title: ^fix\b
|
||||
|
||||
- label: documentation
|
||||
title: ^docs\b
|
||||
|
||||
- label: chore
|
||||
title: ^chore\b
|
||||
|
||||
- label: chore
|
||||
title: ^refactor\b
|
||||
|
||||
- label: build
|
||||
title: ^build\b
|
||||
|
||||
- label: dependencies
|
||||
title: ^build\(deps\)\b
|
||||
@@ -0,0 +1,17 @@
|
||||
changelog:
|
||||
exclude:
|
||||
labels:
|
||||
- dependencies
|
||||
|
||||
categories:
|
||||
- title: Fixes
|
||||
labels:
|
||||
- bug
|
||||
|
||||
- title: Features
|
||||
labels:
|
||||
- enhancement
|
||||
|
||||
- title: Other
|
||||
labels:
|
||||
- '*'
|
||||
@@ -3,6 +3,9 @@ name: Build Syncthing
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches-ignore:
|
||||
- release
|
||||
- release-rc*
|
||||
workflow_call:
|
||||
workflow_dispatch:
|
||||
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
name: PR metadata
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- opened
|
||||
- reopened
|
||||
- edited
|
||||
- synchronize
|
||||
schedule:
|
||||
- cron: "42 7 * * *"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
|
||||
#
|
||||
# Set labels on PRs, which are then used to categorise release notes
|
||||
#
|
||||
|
||||
labels:
|
||||
name: Set labels
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: srvaroa/labeler@v1
|
||||
env:
|
||||
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"slices"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
@@ -37,7 +37,9 @@ func uploadPanicLogs(ctx context.Context, urlBase, dir string) {
|
||||
return
|
||||
}
|
||||
|
||||
sort.Sort(sort.Reverse(sort.StringSlice(files)))
|
||||
slices.SortFunc(files, func(a, b string) int {
|
||||
return strings.Compare(b, a)
|
||||
})
|
||||
for _, file := range files {
|
||||
if strings.Contains(file, ".reported.") {
|
||||
// We've already sent this file. It'll be cleaned out at some
|
||||
|
||||
@@ -5,7 +5,7 @@ go 1.23.0
|
||||
require (
|
||||
github.com/AudriusButkevicius/recli v0.0.7-0.20220911121932-d000ce8fbf0f
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.1
|
||||
github.com/alecthomas/kong v1.10.0
|
||||
github.com/alecthomas/kong v1.11.0
|
||||
github.com/aws/aws-sdk-go v1.55.7
|
||||
github.com/calmh/incontainer v1.0.0
|
||||
github.com/calmh/xdr v1.2.0
|
||||
@@ -30,23 +30,23 @@ require (
|
||||
github.com/pierrec/lz4/v4 v4.1.22
|
||||
github.com/prometheus/client_golang v1.22.0
|
||||
github.com/puzpuzpuz/xsync/v3 v3.5.1
|
||||
github.com/quic-go/quic-go v0.51.0
|
||||
github.com/quic-go/quic-go v0.52.0
|
||||
github.com/rabbitmq/amqp091-go v1.10.0
|
||||
github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9
|
||||
github.com/shirou/gopsutil/v4 v4.25.4
|
||||
github.com/syncthing/notify v0.0.0-20250207082249-f0fa8f99c2bc
|
||||
github.com/syncthing/notify v0.0.0-20250528144937-c7027d4f7465
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d
|
||||
github.com/thejerf/suture/v4 v4.0.6
|
||||
github.com/urfave/cli v1.22.16
|
||||
github.com/vitrun/qart v0.0.0-20160531060029-bf64b92db6b0
|
||||
github.com/willabides/kongplete v0.4.0
|
||||
go.uber.org/automaxprocs v1.6.0
|
||||
golang.org/x/crypto v0.37.0
|
||||
golang.org/x/net v0.39.0
|
||||
golang.org/x/sys v0.32.0
|
||||
golang.org/x/text v0.24.0
|
||||
golang.org/x/crypto v0.38.0
|
||||
golang.org/x/net v0.40.0
|
||||
golang.org/x/sys v0.33.0
|
||||
golang.org/x/text v0.25.0
|
||||
golang.org/x/time v0.11.0
|
||||
golang.org/x/tools v0.32.0
|
||||
golang.org/x/tools v0.33.0
|
||||
google.golang.org/protobuf v1.36.6
|
||||
sigs.k8s.io/yaml v1.4.0
|
||||
)
|
||||
@@ -93,7 +93,7 @@ require (
|
||||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||
go.uber.org/mock v0.5.2 // indirect
|
||||
golang.org/x/mod v0.24.0 // indirect
|
||||
golang.org/x/sync v0.13.0 // indirect
|
||||
golang.org/x/sync v0.14.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@ github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2/go.mod h1:wP83
|
||||
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||
github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0=
|
||||
github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
|
||||
github.com/alecthomas/kong v1.10.0 h1:8K4rGDpT7Iu+jEXCIJUeKqvpwZHbsFRoebLbnzlmrpw=
|
||||
github.com/alecthomas/kong v1.10.0/go.mod h1:p2vqieVMeTAnaC83txKtXe8FLke2X07aruPWXyMPQrU=
|
||||
github.com/alecthomas/kong v1.11.0 h1:y++1gI7jf8O7G7l4LZo5ASFhrhJvzc+WgF/arranEmM=
|
||||
github.com/alecthomas/kong v1.11.0/go.mod h1:p2vqieVMeTAnaC83txKtXe8FLke2X07aruPWXyMPQrU=
|
||||
github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
|
||||
github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
|
||||
github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa h1:LHTHcTQiSGT7VVbI0o4wBRNQIgn917usHWOd6VAffYI=
|
||||
@@ -210,8 +210,8 @@ github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0leargg
|
||||
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
||||
github.com/puzpuzpuz/xsync/v3 v3.5.1 h1:GJYJZwO6IdxN/IKbneznS6yPkVC+c3zyY/j19c++5Fg=
|
||||
github.com/puzpuzpuz/xsync/v3 v3.5.1/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA=
|
||||
github.com/quic-go/quic-go v0.51.0 h1:K8exxe9zXxeRKxaXxi/GpUqYiTrtdiWP8bo1KFya6Wc=
|
||||
github.com/quic-go/quic-go v0.51.0/go.mod h1:MFlGGpcpJqRAfmYi6NC2cptDPSxRWTOGNuP4wqrWmzQ=
|
||||
github.com/quic-go/quic-go v0.52.0 h1:/SlHrCRElyaU6MaEPKqKr9z83sBg2v4FLLvWM+Z47pA=
|
||||
github.com/quic-go/quic-go v0.52.0/go.mod h1:MFlGGpcpJqRAfmYi6NC2cptDPSxRWTOGNuP4wqrWmzQ=
|
||||
github.com/rabbitmq/amqp091-go v1.10.0 h1:STpn5XsHlHGcecLmMFCtg7mqq0RnD+zFr4uzukfVhBw=
|
||||
github.com/rabbitmq/amqp091-go v1.10.0/go.mod h1:Hy4jKW5kQART1u+JkDTF9YYOQUHXqMuhrgxOEeS7G4o=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9 h1:bsUq1dX0N8AOIL7EB/X911+m4EHsnWEHeJ0c+3TTBrg=
|
||||
@@ -240,8 +240,8 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/syncthing/notify v0.0.0-20250207082249-f0fa8f99c2bc h1:xc3UfSFlH/X5hRw3h21RF6WXnRUYKmGRx06FEaVxfkM=
|
||||
github.com/syncthing/notify v0.0.0-20250207082249-f0fa8f99c2bc/go.mod h1:J0q59IWjLtpRIJulohwqEZvjzwOfTEPp8SVhDJl+y0Y=
|
||||
github.com/syncthing/notify v0.0.0-20250528144937-c7027d4f7465 h1:yhxdTGmFkAM2TFA65c3NgGwpnIkUM8oVqPX2e9S7IVg=
|
||||
github.com/syncthing/notify v0.0.0-20250528144937-c7027d4f7465/go.mod h1:J0q59IWjLtpRIJulohwqEZvjzwOfTEPp8SVhDJl+y0Y=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48=
|
||||
github.com/thejerf/suture/v4 v4.0.6 h1:QsuCEsCqb03xF9tPAsWAj8QOAJBgQI1c0VqJNaingg8=
|
||||
@@ -269,8 +269,8 @@ go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
|
||||
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
|
||||
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
|
||||
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
|
||||
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
||||
@@ -282,13 +282,13 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
|
||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
|
||||
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
|
||||
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
||||
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
|
||||
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
|
||||
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -310,23 +310,23 @@ golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
|
||||
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
|
||||
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
|
||||
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
|
||||
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
|
||||
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
|
||||
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU=
|
||||
golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s=
|
||||
golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
|
||||
golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
||||
@@ -117,8 +117,8 @@ func (m *tokenManager) saveLocked() {
|
||||
for token, expiry := range m.tokens.Tokens {
|
||||
tokens = append(tokens, tokenExpiry{token, expiry})
|
||||
}
|
||||
slices.SortFunc(tokens, func(i, j tokenExpiry) int {
|
||||
return int(i.expiry - j.expiry)
|
||||
slices.SortFunc(tokens, func(a, b tokenExpiry) int {
|
||||
return int(a.expiry - b.expiry)
|
||||
})
|
||||
// Remove the oldest tokens.
|
||||
for _, token := range tokens[:len(tokens)-m.maxItems] {
|
||||
|
||||
@@ -18,7 +18,6 @@ import (
|
||||
"os"
|
||||
"reflect"
|
||||
"slices"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@@ -338,8 +337,8 @@ func (cfg *Configuration) prepareDeviceList() map[protocol.DeviceID]*DeviceConfi
|
||||
// - sorted by ID
|
||||
// Happen before preparting folders as that needs a correct device list.
|
||||
cfg.Devices = ensureNoDuplicateOrEmptyIDDevices(cfg.Devices)
|
||||
sort.Slice(cfg.Devices, func(a, b int) bool {
|
||||
return cfg.Devices[a].DeviceID.Compare(cfg.Devices[b].DeviceID) == -1
|
||||
slices.SortFunc(cfg.Devices, func(a, b DeviceConfiguration) int {
|
||||
return a.DeviceID.Compare(b.DeviceID)
|
||||
})
|
||||
|
||||
// Build a list of available devices
|
||||
|
||||
@@ -8,7 +8,7 @@ package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"slices"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
)
|
||||
@@ -100,8 +100,8 @@ func sortedObservedFolderSlice(input map[string]ObservedFolder) []ObservedFolder
|
||||
for _, folder := range input {
|
||||
output = append(output, folder)
|
||||
}
|
||||
sort.Slice(output, func(i, j int) bool {
|
||||
return output[i].Time.Before(output[j].Time)
|
||||
slices.SortFunc(output, func(a, b ObservedFolder) int {
|
||||
return a.Time.Compare(b.Time)
|
||||
})
|
||||
return output
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
"fmt"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"slices"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -291,8 +291,8 @@ func (f *FolderConfiguration) prepare(myID protocol.DeviceID, existingDevices ma
|
||||
f.Devices = ensureDevicePresent(f.Devices, myID)
|
||||
f.Devices = ensureNoUntrustedTrustingSharing(f, f.Devices, existingDevices)
|
||||
|
||||
sort.Slice(f.Devices, func(a, b int) bool {
|
||||
return f.Devices[a].DeviceID.Compare(f.Devices[b].DeviceID) == -1
|
||||
slices.SortFunc(f.Devices, func(a, b FolderDeviceConfiguration) int {
|
||||
return a.DeviceID.Compare(b.DeviceID)
|
||||
})
|
||||
|
||||
if f.RescanIntervalS > MaxRescanIntervalS {
|
||||
|
||||
+3
-3
@@ -8,7 +8,7 @@ package db
|
||||
|
||||
import (
|
||||
"math/bits"
|
||||
"sort"
|
||||
"slices"
|
||||
"testing"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
@@ -71,8 +71,8 @@ func TestMetaDevices(t *testing.T) {
|
||||
}
|
||||
|
||||
// Check that we got the two devices we expect
|
||||
sort.Slice(devs, func(a, b int) bool {
|
||||
return devs[a].Compare(devs[b]) == -1
|
||||
slices.SortFunc(devs, func(a, b protocol.DeviceID) int {
|
||||
return a.Compare(b)
|
||||
})
|
||||
if devs[0] != d1 {
|
||||
t.Error("first device should be d1")
|
||||
|
||||
+19
-26
@@ -11,7 +11,8 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"slices"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -102,16 +103,8 @@ func needList(t testing.TB, s *db.FileSet, n protocol.DeviceID) []protocol.FileI
|
||||
|
||||
type fileList []protocol.FileInfo
|
||||
|
||||
func (l fileList) Len() int {
|
||||
return len(l)
|
||||
}
|
||||
|
||||
func (l fileList) Less(a, b int) bool {
|
||||
return l[a].Name < l[b].Name
|
||||
}
|
||||
|
||||
func (l fileList) Swap(a, b int) {
|
||||
l[a], l[b] = l[b], l[a]
|
||||
func compareByName(a, b protocol.FileInfo) int {
|
||||
return strings.Compare(a.Name, b.Name)
|
||||
}
|
||||
|
||||
func (l fileList) String() string {
|
||||
@@ -218,7 +211,7 @@ func TestGlobalSet(t *testing.T) {
|
||||
t.Helper()
|
||||
|
||||
g := fileList(globalList(t, m))
|
||||
sort.Sort(g)
|
||||
slices.SortFunc(g, compareByName)
|
||||
|
||||
if fmt.Sprint(g) != fmt.Sprint(expectedGlobal) {
|
||||
t.Errorf("Global incorrect;\n A: %v !=\n E: %v", g, expectedGlobal)
|
||||
@@ -255,7 +248,7 @@ func TestGlobalSet(t *testing.T) {
|
||||
}
|
||||
|
||||
h := fileList(haveList(t, m, protocol.LocalDeviceID))
|
||||
sort.Sort(h)
|
||||
slices.SortFunc(h, compareByName)
|
||||
|
||||
if fmt.Sprint(h) != fmt.Sprint(localTot) {
|
||||
t.Errorf("Have incorrect (local);\n A: %v !=\n E: %v", h, localTot)
|
||||
@@ -292,14 +285,14 @@ func TestGlobalSet(t *testing.T) {
|
||||
}
|
||||
|
||||
h = fileList(haveList(t, m, remoteDevice0))
|
||||
sort.Sort(h)
|
||||
slices.SortFunc(h, compareByName)
|
||||
|
||||
if fmt.Sprint(h) != fmt.Sprint(remoteTot) {
|
||||
t.Errorf("Have incorrect (remote);\n A: %v !=\n E: %v", h, remoteTot)
|
||||
}
|
||||
|
||||
n := fileList(needList(t, m, protocol.LocalDeviceID))
|
||||
sort.Sort(n)
|
||||
slices.SortFunc(n, compareByName)
|
||||
|
||||
if fmt.Sprint(n) != fmt.Sprint(expectedLocalNeed) {
|
||||
t.Errorf("Need incorrect (local);\n A: %v !=\n E: %v", n, expectedLocalNeed)
|
||||
@@ -308,7 +301,7 @@ func TestGlobalSet(t *testing.T) {
|
||||
checkNeed(t, m, protocol.LocalDeviceID, expectedLocalNeed)
|
||||
|
||||
n = fileList(needList(t, m, remoteDevice0))
|
||||
sort.Sort(n)
|
||||
slices.SortFunc(n, compareByName)
|
||||
|
||||
if fmt.Sprint(n) != fmt.Sprint(expectedRemoteNeed) {
|
||||
t.Errorf("Need incorrect (remote);\n A: %v !=\n E: %v", n, expectedRemoteNeed)
|
||||
@@ -428,14 +421,14 @@ func TestGlobalSet(t *testing.T) {
|
||||
check()
|
||||
|
||||
h := fileList(haveList(t, m, remoteDevice1))
|
||||
sort.Sort(h)
|
||||
slices.SortFunc(h, compareByName)
|
||||
|
||||
if fmt.Sprint(h) != fmt.Sprint(secRemote) {
|
||||
t.Errorf("Have incorrect (secRemote);\n A: %v !=\n E: %v", h, secRemote)
|
||||
}
|
||||
|
||||
n := fileList(needList(t, m, remoteDevice1))
|
||||
sort.Sort(n)
|
||||
slices.SortFunc(n, compareByName)
|
||||
|
||||
if fmt.Sprint(n) != fmt.Sprint(expectedSecRemoteNeed) {
|
||||
t.Errorf("Need incorrect (secRemote);\n A: %v !=\n E: %v", n, expectedSecRemoteNeed)
|
||||
@@ -475,7 +468,7 @@ func TestNeedWithInvalid(t *testing.T) {
|
||||
replace(s, remoteDevice1, remote1Have)
|
||||
|
||||
need := fileList(needList(t, s, protocol.LocalDeviceID))
|
||||
sort.Sort(need)
|
||||
slices.SortFunc(need, compareByName)
|
||||
|
||||
if fmt.Sprint(need) != fmt.Sprint(expectedNeed) {
|
||||
t.Errorf("Need incorrect;\n A: %v !=\n E: %v", need, expectedNeed)
|
||||
@@ -503,7 +496,7 @@ func TestUpdateToInvalid(t *testing.T) {
|
||||
replace(s, protocol.LocalDeviceID, localHave)
|
||||
|
||||
have := fileList(haveList(t, s, protocol.LocalDeviceID))
|
||||
sort.Sort(have)
|
||||
slices.SortFunc(have, compareByName)
|
||||
|
||||
if fmt.Sprint(have) != fmt.Sprint(localHave) {
|
||||
t.Errorf("Have incorrect before invalidation;\n A: %v !=\n E: %v", have, localHave)
|
||||
@@ -519,8 +512,8 @@ func TestUpdateToInvalid(t *testing.T) {
|
||||
|
||||
s.Update(protocol.LocalDeviceID, append(fileList{}, localHave[1], localHave[4]))
|
||||
|
||||
have = fileList(haveList(t, s, protocol.LocalDeviceID))
|
||||
sort.Sort(have)
|
||||
have = haveList(t, s, protocol.LocalDeviceID)
|
||||
slices.SortFunc(have, compareByName)
|
||||
|
||||
if fmt.Sprint(have) != fmt.Sprint(localHave) {
|
||||
t.Errorf("Have incorrect after invalidation;\n A: %v !=\n E: %v", have, localHave)
|
||||
@@ -605,7 +598,7 @@ func TestGlobalReset(t *testing.T) {
|
||||
|
||||
replace(m, protocol.LocalDeviceID, local)
|
||||
g := globalList(t, m)
|
||||
sort.Sort(fileList(g))
|
||||
slices.SortFunc(g, compareByName)
|
||||
|
||||
if diff, equal := messagediff.PrettyDiff(local, g); !equal {
|
||||
t.Errorf("Global incorrect;\nglobal: %v\n!=\nlocal: %v\ndiff:\n%s", g, local, diff)
|
||||
@@ -615,7 +608,7 @@ func TestGlobalReset(t *testing.T) {
|
||||
replace(m, remoteDevice0, nil)
|
||||
|
||||
g = globalList(t, m)
|
||||
sort.Sort(fileList(g))
|
||||
slices.SortFunc(g, compareByName)
|
||||
|
||||
if diff, equal := messagediff.PrettyDiff(local, g); !equal {
|
||||
t.Errorf("Global incorrect;\nglobal: %v\n!=\nlocal: %v\ndiff:\n%s", g, local, diff)
|
||||
@@ -653,8 +646,8 @@ func TestNeed(t *testing.T) {
|
||||
|
||||
need := needList(t, m, protocol.LocalDeviceID)
|
||||
|
||||
sort.Sort(fileList(need))
|
||||
sort.Sort(fileList(shouldNeed))
|
||||
slices.SortFunc(need, compareByName)
|
||||
slices.SortFunc(shouldNeed, compareByName)
|
||||
|
||||
if fmt.Sprint(need) != fmt.Sprint(shouldNeed) {
|
||||
t.Errorf("Need incorrect;\n%v !=\n%v", need, shouldNeed)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"slices"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
@@ -52,8 +52,8 @@ type standardBlockPullReorderer struct {
|
||||
|
||||
func newStandardBlockPullReorderer(id protocol.DeviceID, otherDevices []protocol.DeviceID) *standardBlockPullReorderer {
|
||||
allDevices := append(otherDevices, id)
|
||||
sort.Slice(allDevices, func(i, j int) bool {
|
||||
return allDevices[i].Compare(allDevices[j]) == -1
|
||||
slices.SortFunc(allDevices, func(a, b protocol.DeviceID) int {
|
||||
return a.Compare(b)
|
||||
})
|
||||
// Find our index
|
||||
myIndex := -1
|
||||
|
||||
@@ -8,7 +8,7 @@ package model
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sort"
|
||||
"slices"
|
||||
"testing"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
@@ -65,8 +65,8 @@ func Test_inOrderBlockPullReorderer_Reorder(t *testing.T) {
|
||||
func Test_standardBlockPullReorderer_Reorder(t *testing.T) {
|
||||
// Order the devices, so we know their ordering ahead of time.
|
||||
devices := []protocol.DeviceID{myID, device1, device2}
|
||||
sort.Slice(devices, func(i, j int) bool {
|
||||
return devices[i].Compare(devices[j]) == -1
|
||||
slices.SortFunc(devices, func(a, b protocol.DeviceID) int {
|
||||
return a.Compare(b)
|
||||
})
|
||||
|
||||
blocks := func(i ...int) []protocol.BlockInfo {
|
||||
|
||||
+4
-2
@@ -13,7 +13,7 @@ import (
|
||||
"math/rand"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
@@ -1201,7 +1201,9 @@ func (f *folder) Errors() []FileError {
|
||||
errors := make([]FileError, scanLen+len(f.pullErrors))
|
||||
copy(errors[:scanLen], f.scanErrors)
|
||||
copy(errors[scanLen:], f.pullErrors)
|
||||
sort.Sort(fileErrorList(errors))
|
||||
slices.SortFunc(errors, func(a, b FileError) int {
|
||||
return strings.Compare(a.Path, b.Path)
|
||||
})
|
||||
return errors
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,8 @@ package model
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/db"
|
||||
@@ -112,7 +113,9 @@ func (f *receiveEncryptedFolder) revertHandleDirs(dirs []string, snap *db.Snapsh
|
||||
go f.pullScannerRoutine(scanChan)
|
||||
defer close(scanChan)
|
||||
|
||||
sort.Sort(sort.Reverse(sort.StringSlice(dirs)))
|
||||
slices.SortFunc(dirs, func(a, b string) int {
|
||||
return strings.Compare(b, a)
|
||||
})
|
||||
for _, dir := range dirs {
|
||||
if err := f.deleteDirOnDisk(dir, snap, scanChan); err != nil {
|
||||
f.newScanError(dir, fmt.Errorf("deleting unexpected dir: %w", err))
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"slices"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
@@ -207,7 +208,9 @@ func (q *deleteQueue) handle(fi protocol.FileInfo, snap *db.Snapshot) (bool, err
|
||||
|
||||
func (q *deleteQueue) flush(snap *db.Snapshot) ([]string, error) {
|
||||
// Process directories from the leaves inward.
|
||||
sort.Sort(sort.Reverse(sort.StringSlice(q.dirs)))
|
||||
slices.SortFunc(q.dirs, func(a, b string) int {
|
||||
return strings.Compare(b, a)
|
||||
})
|
||||
|
||||
var firstError error
|
||||
var deleted []string
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -1867,7 +1867,9 @@ func (f *sendReceiveFolder) moveForConflict(name, lastModBy string, scanChan cha
|
||||
if f.MaxConflicts > -1 {
|
||||
matches := existingConflicts(name, f.mtimefs)
|
||||
if len(matches) > f.MaxConflicts {
|
||||
sort.Sort(sort.Reverse(sort.StringSlice(matches)))
|
||||
slices.SortFunc(matches, func(a, b string) int {
|
||||
return strings.Compare(b, a)
|
||||
})
|
||||
for _, match := range matches[f.MaxConflicts:] {
|
||||
if gerr := f.mtimefs.Remove(match); gerr != nil {
|
||||
l.Debugln(f, "removing extra conflict", gerr)
|
||||
@@ -2206,20 +2208,6 @@ type FileError struct {
|
||||
Err string `json:"error"`
|
||||
}
|
||||
|
||||
type fileErrorList []FileError
|
||||
|
||||
func (l fileErrorList) Len() int {
|
||||
return len(l)
|
||||
}
|
||||
|
||||
func (l fileErrorList) Less(a, b int) bool {
|
||||
return l[a].Path < l[b].Path
|
||||
}
|
||||
|
||||
func (l fileErrorList) Swap(a, b int) {
|
||||
l[a], l[b] = l[b], l[a]
|
||||
}
|
||||
|
||||
func conflictName(name, lastModBy string) string {
|
||||
ext := filepath.Ext(name)
|
||||
return name[:len(name)-len(ext)] + time.Now().Format(".sync-conflict-20060102-150405-") + lastModBy + ext
|
||||
|
||||
+14
-19
@@ -7,7 +7,8 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"cmp"
|
||||
"slices"
|
||||
"time"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/rand"
|
||||
@@ -157,40 +158,34 @@ func (q *jobQueue) SortSmallestFirst() {
|
||||
q.mut.Lock()
|
||||
defer q.mut.Unlock()
|
||||
|
||||
sort.Sort(smallestFirst(q.queued))
|
||||
slices.SortFunc(q.queued, func(a, b jobQueueEntry) int {
|
||||
return cmp.Compare(a.size, b.size)
|
||||
})
|
||||
}
|
||||
|
||||
func (q *jobQueue) SortLargestFirst() {
|
||||
q.mut.Lock()
|
||||
defer q.mut.Unlock()
|
||||
|
||||
sort.Sort(sort.Reverse(smallestFirst(q.queued)))
|
||||
slices.SortFunc(q.queued, func(a, b jobQueueEntry) int {
|
||||
return cmp.Compare(b.size, a.size)
|
||||
})
|
||||
}
|
||||
|
||||
func (q *jobQueue) SortOldestFirst() {
|
||||
q.mut.Lock()
|
||||
defer q.mut.Unlock()
|
||||
|
||||
sort.Sort(oldestFirst(q.queued))
|
||||
slices.SortFunc(q.queued, func(a, b jobQueueEntry) int {
|
||||
return cmp.Compare(a.modified, b.modified)
|
||||
})
|
||||
}
|
||||
|
||||
func (q *jobQueue) SortNewestFirst() {
|
||||
q.mut.Lock()
|
||||
defer q.mut.Unlock()
|
||||
|
||||
sort.Sort(sort.Reverse(oldestFirst(q.queued)))
|
||||
slices.SortFunc(q.queued, func(a, b jobQueueEntry) int {
|
||||
return cmp.Compare(b.modified, a.modified)
|
||||
})
|
||||
}
|
||||
|
||||
// The usual sort.Interface boilerplate
|
||||
|
||||
type smallestFirst []jobQueueEntry
|
||||
|
||||
func (q smallestFirst) Len() int { return len(q) }
|
||||
func (q smallestFirst) Less(a, b int) bool { return q[a].size < q[b].size }
|
||||
func (q smallestFirst) Swap(a, b int) { q[a], q[b] = q[b], q[a] }
|
||||
|
||||
type oldestFirst []jobQueueEntry
|
||||
|
||||
func (q oldestFirst) Len() int { return len(q) }
|
||||
func (q oldestFirst) Less(a, b int) bool { return q[a].modified < q[b].modified }
|
||||
func (q oldestFirst) Swap(a, b int) { q[a], q[b] = q[b], q[a] }
|
||||
|
||||
@@ -16,7 +16,8 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
rdebug "runtime/debug"
|
||||
"sort"
|
||||
"slices"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
@@ -145,7 +146,7 @@ func TestWalk(t *testing.T) {
|
||||
}
|
||||
tmp = append(tmp, f.File)
|
||||
}
|
||||
sort.Sort(fileList(tmp))
|
||||
slices.SortFunc(fileList(tmp), compareByName)
|
||||
files := fileList(tmp).testfiles()
|
||||
|
||||
if diff, equal := messagediff.PrettyDiff(testdata, files); !equal {
|
||||
@@ -584,23 +585,15 @@ func walkDir(fs fs.Filesystem, dir string, cfiler CurrentFiler, matcher *ignore.
|
||||
tmp = append(tmp, f.File)
|
||||
}
|
||||
}
|
||||
sort.Sort(fileList(tmp))
|
||||
slices.SortFunc(fileList(tmp), compareByName)
|
||||
|
||||
return tmp
|
||||
}
|
||||
|
||||
type fileList []protocol.FileInfo
|
||||
|
||||
func (l fileList) Len() int {
|
||||
return len(l)
|
||||
}
|
||||
|
||||
func (l fileList) Less(a, b int) bool {
|
||||
return l[a].Name < l[b].Name
|
||||
}
|
||||
|
||||
func (l fileList) Swap(a, b int) {
|
||||
l[a], l[b] = l[b], l[a]
|
||||
func compareByName(a, b protocol.FileInfo) int {
|
||||
return strings.Compare(a.Name, b.Name)
|
||||
}
|
||||
|
||||
func (l fileList) testfiles() testfileList {
|
||||
@@ -825,7 +818,7 @@ func TestIssue4841(t *testing.T) {
|
||||
}
|
||||
files = append(files, f.File)
|
||||
}
|
||||
sort.Sort(fileList(files))
|
||||
slices.SortFunc(fileList(files), compareByName)
|
||||
|
||||
if len(files) != 1 {
|
||||
t.Fatalf("Expected 1 file, got %d: %v", len(files), files)
|
||||
|
||||
@@ -8,7 +8,8 @@ package versioner
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/fs"
|
||||
)
|
||||
@@ -37,7 +38,9 @@ func (t emptyDirTracker) emptyDirs() []string {
|
||||
for dir := range t {
|
||||
empty = append(empty, dir)
|
||||
}
|
||||
sort.Sort(sort.Reverse(sort.StringSlice(empty)))
|
||||
slices.SortFunc(empty, func(a, b string) int {
|
||||
return strings.Compare(b, a)
|
||||
})
|
||||
return empty
|
||||
}
|
||||
|
||||
|
||||
@@ -16,3 +16,6 @@ example:
|
||||
|
||||
The release notes will also be included in candidate releases (e.g.
|
||||
v1.2.3-rc.1).
|
||||
|
||||
Additional notes will also be loaded from `v1.2.md` and `v1.md`, if they
|
||||
exist.
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
## Syncthing 2 is coming
|
||||
|
||||
Syncthing version 1.x will soon be replaced by Syncthing version 2.x.
|
||||
Version 2 brings a new database format and various cleanups, but remains
|
||||
protocol compatible with Syncthing 1.
|
||||
|
||||
More detailed information about Syncthing 2 can be found in the release
|
||||
notes at https://github.com/syncthing/syncthing/releases.
|
||||
+17
-31
@@ -14,6 +14,7 @@ package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"cmp"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
@@ -21,7 +22,7 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"sort"
|
||||
"slices"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@@ -102,7 +103,17 @@ func main() {
|
||||
// Write author names in GUI about modal
|
||||
|
||||
getContributions(authors)
|
||||
sort.Sort(byContributions(authors))
|
||||
|
||||
// Sort by contributions
|
||||
slices.SortFunc(authors, func(a, b author) int {
|
||||
// Sort first by log10(commits), then by name. This means that we first get
|
||||
// an alphabetic list of people with >= 1000 commits, then a list of people
|
||||
// with >= 100 commits, and so on.
|
||||
if a.log10commits != b.log10commits {
|
||||
return cmp.Compare(b.log10commits, a.log10commits)
|
||||
}
|
||||
return strings.Compare(a.name, b.name)
|
||||
})
|
||||
|
||||
var lines []string
|
||||
for _, author := range authors {
|
||||
@@ -125,7 +136,10 @@ func main() {
|
||||
|
||||
// Write AUTHORS file
|
||||
|
||||
sort.Sort(byName(authors))
|
||||
// Sort by author name
|
||||
slices.SortFunc(authors, func(a, b author) int {
|
||||
return strings.Compare(strings.ToLower(a.name), strings.ToLower(b.name))
|
||||
})
|
||||
|
||||
out, err := os.Create("AUTHORS")
|
||||
if err != nil {
|
||||
@@ -298,34 +312,6 @@ func allAuthors() map[string]string {
|
||||
return names
|
||||
}
|
||||
|
||||
type byContributions []author
|
||||
|
||||
func (l byContributions) Len() int { return len(l) }
|
||||
|
||||
// Sort first by log10(commits), then by name. This means that we first get
|
||||
// an alphabetic list of people with >= 1000 commits, then a list of people
|
||||
// with >= 100 commits, and so on.
|
||||
func (l byContributions) Less(a, b int) bool {
|
||||
if l[a].log10commits != l[b].log10commits {
|
||||
return l[a].log10commits > l[b].log10commits
|
||||
}
|
||||
return l[a].name < l[b].name
|
||||
}
|
||||
|
||||
func (l byContributions) Swap(a, b int) { l[a], l[b] = l[b], l[a] }
|
||||
|
||||
type byName []author
|
||||
|
||||
func (l byName) Len() int { return len(l) }
|
||||
|
||||
func (l byName) Less(a, b int) bool {
|
||||
aname := strings.ToLower(l[a].name)
|
||||
bname := strings.ToLower(l[b].name)
|
||||
return aname < bname
|
||||
}
|
||||
|
||||
func (l byName) Swap(a, b int) { l[a], l[b] = l[b], l[a] }
|
||||
|
||||
// A simple string set type
|
||||
|
||||
type stringSet map[string]struct{}
|
||||
|
||||
+26
-12
@@ -20,6 +20,7 @@ import (
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@@ -43,29 +44,38 @@ func main() {
|
||||
log.Fatalln("Must set $GITHUB_TOKEN")
|
||||
}
|
||||
|
||||
addl, err := additionalNotes(*ver)
|
||||
notes, err := additionalNotes(*ver)
|
||||
if err != nil {
|
||||
log.Fatalln("Gathering additional notes:", err)
|
||||
}
|
||||
notes, err := generatedNotes(*ver, *branch, *prevVer)
|
||||
gh, err := generatedNotes(*ver, *branch, *prevVer)
|
||||
if err != nil {
|
||||
log.Fatalln("Gathering github notes:", err)
|
||||
}
|
||||
notes = append(notes, gh)
|
||||
|
||||
if addl != "" {
|
||||
fmt.Println(addl)
|
||||
}
|
||||
fmt.Println(notes)
|
||||
fmt.Println(strings.Join(notes, "\n\n"))
|
||||
}
|
||||
|
||||
// Load potential additional release notes from within the repo
|
||||
func additionalNotes(newVer string) (string, error) {
|
||||
func additionalNotes(newVer string) ([]string, error) {
|
||||
var notes []string
|
||||
ver, _, _ := strings.Cut(newVer, "-")
|
||||
bs, err := os.ReadFile(fmt.Sprintf("relnotes/%s.md", ver))
|
||||
if os.IsNotExist(err) {
|
||||
return "", nil
|
||||
for {
|
||||
file := fmt.Sprintf("relnotes/%s.md", ver)
|
||||
if bs, err := os.ReadFile(file); err == nil {
|
||||
notes = append(notes, strings.TrimSpace(string(bs)))
|
||||
} else if !os.IsNotExist(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if idx := strings.LastIndex(ver, "."); idx > 0 {
|
||||
ver = ver[:idx]
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
return string(bs), err
|
||||
return notes, nil
|
||||
}
|
||||
|
||||
// Load generated release notes (list of pull requests and contributors)
|
||||
@@ -105,5 +115,9 @@ func generatedNotes(newVer, targetCommit, prevVer string) (string, error) {
|
||||
if err := json.NewDecoder(res.Body).Decode(&resJSON); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return resJSON.Body, nil
|
||||
return strings.TrimSpace(removeHTMLComments(resJSON.Body)), nil
|
||||
}
|
||||
|
||||
func removeHTMLComments(s string) string {
|
||||
return regexp.MustCompile(`<!--.*?-->`).ReplaceAllString(s, "")
|
||||
}
|
||||
|
||||
+4
-16
@@ -20,7 +20,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sort"
|
||||
"slices"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -375,7 +375,9 @@ func mergeDirectoryContents(c ...[]fileInfo) []fileInfo {
|
||||
i++
|
||||
}
|
||||
|
||||
sort.Sort(fileInfoList(res))
|
||||
slices.SortFunc(res, func(a, b fileInfo) int {
|
||||
return strings.Compare(a.name, b.name)
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
@@ -404,20 +406,6 @@ func (f fileInfo) String() string {
|
||||
return fmt.Sprintf("%s %04o %d %x", f.name, f.mode, f.mod, f.hash)
|
||||
}
|
||||
|
||||
type fileInfoList []fileInfo
|
||||
|
||||
func (l fileInfoList) Len() int {
|
||||
return len(l)
|
||||
}
|
||||
|
||||
func (l fileInfoList) Less(a, b int) bool {
|
||||
return l[a].name < l[b].name
|
||||
}
|
||||
|
||||
func (l fileInfoList) Swap(a, b int) {
|
||||
l[a], l[b] = l[b], l[a]
|
||||
}
|
||||
|
||||
func startWalker(dir string, res chan<- fileInfo, abort <-chan struct{}) chan error {
|
||||
walker := func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user