Merge branch 'main' into v2

* main:
  refactor: use slices package for sorting (#10136)
  build: handle multiple general release notes
  build: no need to build on the branches that just trigger tags
This commit is contained in:
Jakob Borg
2025-05-26 21:40:54 +02:00
18 changed files with 86 additions and 85 deletions
+3
View File
@@ -3,6 +3,9 @@ name: Build Syncthing
on: on:
pull_request: pull_request:
push: push:
branches-ignore:
- release
- release-rc*
workflow_call: workflow_call:
workflow_dispatch: workflow_dispatch:
+4 -2
View File
@@ -14,7 +14,7 @@ import (
"net/http" "net/http"
"os" "os"
"path/filepath" "path/filepath"
"sort" "slices"
"strings" "strings"
"time" "time"
) )
@@ -37,7 +37,9 @@ func uploadPanicLogs(ctx context.Context, urlBase, dir string) {
return 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 { for _, file := range files {
if strings.Contains(file, ".reported.") { if strings.Contains(file, ".reported.") {
// We've already sent this file. It'll be cleaned out at some // We've already sent this file. It'll be cleaned out at some
+2 -2
View File
@@ -117,8 +117,8 @@ func (m *tokenManager) saveLocked() {
for token, expiry := range m.tokens.Tokens { for token, expiry := range m.tokens.Tokens {
tokens = append(tokens, tokenExpiry{token, expiry}) tokens = append(tokens, tokenExpiry{token, expiry})
} }
slices.SortFunc(tokens, func(i, j tokenExpiry) int { slices.SortFunc(tokens, func(a, b tokenExpiry) int {
return int(i.expiry - j.expiry) return int(a.expiry - b.expiry)
}) })
// Remove the oldest tokens. // Remove the oldest tokens.
for _, token := range tokens[:len(tokens)-m.maxItems] { for _, token := range tokens[:len(tokens)-m.maxItems] {
+2 -3
View File
@@ -18,7 +18,6 @@ import (
"os" "os"
"reflect" "reflect"
"slices" "slices"
"sort"
"strconv" "strconv"
"strings" "strings"
@@ -338,8 +337,8 @@ func (cfg *Configuration) prepareDeviceList() map[protocol.DeviceID]*DeviceConfi
// - sorted by ID // - sorted by ID
// Happen before preparting folders as that needs a correct device list. // Happen before preparting folders as that needs a correct device list.
cfg.Devices = ensureNoDuplicateOrEmptyIDDevices(cfg.Devices) cfg.Devices = ensureNoDuplicateOrEmptyIDDevices(cfg.Devices)
sort.Slice(cfg.Devices, func(a, b int) bool { slices.SortFunc(cfg.Devices, func(a, b DeviceConfiguration) int {
return cfg.Devices[a].DeviceID.Compare(cfg.Devices[b].DeviceID) == -1 return a.DeviceID.Compare(b.DeviceID)
}) })
// Build a list of available devices // Build a list of available devices
+3 -3
View File
@@ -8,7 +8,7 @@ package config
import ( import (
"fmt" "fmt"
"sort" "slices"
"github.com/syncthing/syncthing/lib/protocol" "github.com/syncthing/syncthing/lib/protocol"
) )
@@ -100,8 +100,8 @@ func sortedObservedFolderSlice(input map[string]ObservedFolder) []ObservedFolder
for _, folder := range input { for _, folder := range input {
output = append(output, folder) output = append(output, folder)
} }
sort.Slice(output, func(i, j int) bool { slices.SortFunc(output, func(a, b ObservedFolder) int {
return output[i].Time.Before(output[j].Time) return a.Time.Compare(b.Time)
}) })
return output return output
} }
+3 -3
View File
@@ -15,7 +15,7 @@ import (
"fmt" "fmt"
"path" "path"
"path/filepath" "path/filepath"
"sort" "slices"
"strings" "strings"
"time" "time"
@@ -288,8 +288,8 @@ func (f *FolderConfiguration) prepare(myID protocol.DeviceID, existingDevices ma
f.Devices = ensureDevicePresent(f.Devices, myID) f.Devices = ensureDevicePresent(f.Devices, myID)
f.Devices = ensureNoUntrustedTrustingSharing(f, f.Devices, existingDevices) f.Devices = ensureNoUntrustedTrustingSharing(f, f.Devices, existingDevices)
sort.Slice(f.Devices, func(a, b int) bool { slices.SortFunc(f.Devices, func(a, b FolderDeviceConfiguration) int {
return f.Devices[a].DeviceID.Compare(f.Devices[b].DeviceID) == -1 return a.DeviceID.Compare(b.DeviceID)
}) })
if f.RescanIntervalS > MaxRescanIntervalS { if f.RescanIntervalS > MaxRescanIntervalS {
+3 -3
View File
@@ -7,7 +7,7 @@
package model package model
import ( import (
"sort" "slices"
"github.com/syncthing/syncthing/lib/config" "github.com/syncthing/syncthing/lib/config"
"github.com/syncthing/syncthing/lib/protocol" "github.com/syncthing/syncthing/lib/protocol"
@@ -52,8 +52,8 @@ type standardBlockPullReorderer struct {
func newStandardBlockPullReorderer(id protocol.DeviceID, otherDevices []protocol.DeviceID) *standardBlockPullReorderer { func newStandardBlockPullReorderer(id protocol.DeviceID, otherDevices []protocol.DeviceID) *standardBlockPullReorderer {
allDevices := append(otherDevices, id) allDevices := append(otherDevices, id)
sort.Slice(allDevices, func(i, j int) bool { slices.SortFunc(allDevices, func(a, b protocol.DeviceID) int {
return allDevices[i].Compare(allDevices[j]) == -1 return a.Compare(b)
}) })
// Find our index // Find our index
myIndex := -1 myIndex := -1
+3 -3
View File
@@ -8,7 +8,7 @@ package model
import ( import (
"reflect" "reflect"
"sort" "slices"
"testing" "testing"
"github.com/syncthing/syncthing/lib/protocol" "github.com/syncthing/syncthing/lib/protocol"
@@ -65,8 +65,8 @@ func Test_inOrderBlockPullReorderer_Reorder(t *testing.T) {
func Test_standardBlockPullReorderer_Reorder(t *testing.T) { func Test_standardBlockPullReorderer_Reorder(t *testing.T) {
// Order the devices, so we know their ordering ahead of time. // Order the devices, so we know their ordering ahead of time.
devices := []protocol.DeviceID{myID, device1, device2} devices := []protocol.DeviceID{myID, device1, device2}
sort.Slice(devices, func(i, j int) bool { slices.SortFunc(devices, func(a, b protocol.DeviceID) int {
return devices[i].Compare(devices[j]) == -1 return a.Compare(b)
}) })
blocks := func(i ...int) []protocol.BlockInfo { blocks := func(i ...int) []protocol.BlockInfo {
+4 -2
View File
@@ -13,7 +13,7 @@ import (
"math/rand" "math/rand"
"path/filepath" "path/filepath"
"slices" "slices"
"sort" "strings"
"time" "time"
"github.com/syncthing/syncthing/internal/db" "github.com/syncthing/syncthing/internal/db"
@@ -1226,7 +1226,9 @@ func (f *folder) Errors() []FileError {
errors := make([]FileError, scanLen+len(f.pullErrors)) errors := make([]FileError, scanLen+len(f.pullErrors))
copy(errors[:scanLen], f.scanErrors) copy(errors[:scanLen], f.scanErrors)
copy(errors[scanLen:], f.pullErrors) 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 return errors
} }
+5 -2
View File
@@ -8,7 +8,8 @@ package model
import ( import (
"fmt" "fmt"
"sort" "slices"
"strings"
"github.com/syncthing/syncthing/internal/itererr" "github.com/syncthing/syncthing/internal/itererr"
"github.com/syncthing/syncthing/lib/config" "github.com/syncthing/syncthing/lib/config"
@@ -104,7 +105,9 @@ func (f *receiveEncryptedFolder) revertHandleDirs(dirs []string) {
go f.pullScannerRoutine(scanChan) go f.pullScannerRoutine(scanChan)
defer close(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 { for _, dir := range dirs {
if err := f.deleteDirOnDisk(dir, scanChan); err != nil { if err := f.deleteDirOnDisk(dir, scanChan); err != nil {
f.newScanError(dir, fmt.Errorf("deleting unexpected dir: %w", err)) f.newScanError(dir, fmt.Errorf("deleting unexpected dir: %w", err))
+5 -2
View File
@@ -7,7 +7,8 @@
package model package model
import ( import (
"sort" "slices"
"strings"
"time" "time"
"github.com/syncthing/syncthing/internal/itererr" "github.com/syncthing/syncthing/internal/itererr"
@@ -208,7 +209,9 @@ func (q *deleteQueue) handle(fi protocol.FileInfo) (bool, error) {
func (q *deleteQueue) flush() ([]string, error) { func (q *deleteQueue) flush() ([]string, error) {
// Process directories from the leaves inward. // 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 firstError error
var deleted []string var deleted []string
+4 -16
View File
@@ -14,7 +14,7 @@ import (
"fmt" "fmt"
"io" "io"
"path/filepath" "path/filepath"
"sort" "slices"
"strconv" "strconv"
"strings" "strings"
"time" "time"
@@ -1854,7 +1854,9 @@ func (f *sendReceiveFolder) moveForConflict(name, lastModBy string, scanChan cha
if f.MaxConflicts > -1 { if f.MaxConflicts > -1 {
matches := existingConflicts(name, f.mtimefs) matches := existingConflicts(name, f.mtimefs)
if len(matches) > f.MaxConflicts { 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:] { for _, match := range matches[f.MaxConflicts:] {
if gerr := f.mtimefs.Remove(match); gerr != nil { if gerr := f.mtimefs.Remove(match); gerr != nil {
l.Debugln(f, "removing extra conflict", gerr) l.Debugln(f, "removing extra conflict", gerr)
@@ -2196,20 +2198,6 @@ type FileError struct {
Err string `json:"error"` 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 { func conflictName(name, lastModBy string) string {
ext := filepath.Ext(name) ext := filepath.Ext(name)
return name[:len(name)-len(ext)] + time.Now().Format(".sync-conflict-20060102-150405-") + lastModBy + ext return name[:len(name)-len(ext)] + time.Now().Format(".sync-conflict-20060102-150405-") + lastModBy + ext
+7 -14
View File
@@ -16,7 +16,8 @@ import (
"os" "os"
"path/filepath" "path/filepath"
rdebug "runtime/debug" rdebug "runtime/debug"
"sort" "slices"
"strings"
"sync" "sync"
"testing" "testing"
@@ -145,7 +146,7 @@ func TestWalk(t *testing.T) {
} }
tmp = append(tmp, f.File) tmp = append(tmp, f.File)
} }
sort.Sort(fileList(tmp)) slices.SortFunc(fileList(tmp), compareByName)
files := fileList(tmp).testfiles() files := fileList(tmp).testfiles()
if diff, equal := messagediff.PrettyDiff(testdata, files); !equal { 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) tmp = append(tmp, f.File)
} }
} }
sort.Sort(fileList(tmp)) slices.SortFunc(fileList(tmp), compareByName)
return tmp return tmp
} }
type fileList []protocol.FileInfo type fileList []protocol.FileInfo
func (l fileList) Len() int { func compareByName(a, b protocol.FileInfo) int {
return len(l) return strings.Compare(a.Name, b.Name)
}
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 (l fileList) testfiles() testfileList { func (l fileList) testfiles() testfileList {
@@ -825,7 +818,7 @@ func TestIssue4841(t *testing.T) {
} }
files = append(files, f.File) files = append(files, f.File)
} }
sort.Sort(fileList(files)) slices.SortFunc(fileList(files), compareByName)
if len(files) != 1 { if len(files) != 1 {
t.Fatalf("Expected 1 file, got %d: %v", len(files), files) t.Fatalf("Expected 1 file, got %d: %v", len(files), files)
+5 -2
View File
@@ -8,7 +8,8 @@ package versioner
import ( import (
"path/filepath" "path/filepath"
"sort" "slices"
"strings"
"github.com/syncthing/syncthing/lib/fs" "github.com/syncthing/syncthing/lib/fs"
) )
@@ -37,7 +38,9 @@ func (t emptyDirTracker) emptyDirs() []string {
for dir := range t { for dir := range t {
empty = append(empty, dir) 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 return empty
} }
+3
View File
@@ -16,3 +16,6 @@ example:
The release notes will also be included in candidate releases (e.g. The release notes will also be included in candidate releases (e.g.
v1.2.3-rc.1). v1.2.3-rc.1).
Additional notes will also be loaded from `v1.2.md` and `v1.md`, if they
exist.
+5
View File
@@ -99,6 +99,11 @@ func main() {
// Write AUTHORS file // Write AUTHORS file
// 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") out, err := os.Create("AUTHORS")
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
+21 -12
View File
@@ -43,29 +43,38 @@ func main() {
log.Fatalln("Must set $GITHUB_TOKEN") log.Fatalln("Must set $GITHUB_TOKEN")
} }
addl, err := additionalNotes(*ver) notes, err := additionalNotes(*ver)
if err != nil { if err != nil {
log.Fatalln("Gathering additional notes:", err) log.Fatalln("Gathering additional notes:", err)
} }
notes, err := generatedNotes(*ver, *branch, *prevVer) gh, err := generatedNotes(*ver, *branch, *prevVer)
if err != nil { if err != nil {
log.Fatalln("Gathering github notes:", err) log.Fatalln("Gathering github notes:", err)
} }
notes = append(notes, gh)
if addl != "" { fmt.Println(strings.Join(notes, "\n\n"))
fmt.Println(addl)
}
fmt.Println(notes)
} }
// Load potential additional release notes from within the repo // 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, "-") ver, _, _ := strings.Cut(newVer, "-")
bs, err := os.ReadFile(fmt.Sprintf("relnotes/%s.md", ver)) for {
if os.IsNotExist(err) { file := fmt.Sprintf("relnotes/%s.md", ver)
return "", nil 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) // Load generated release notes (list of pull requests and contributors)
@@ -105,5 +114,5 @@ func generatedNotes(newVer, targetCommit, prevVer string) (string, error) {
if err := json.NewDecoder(res.Body).Decode(&resJSON); err != nil { if err := json.NewDecoder(res.Body).Decode(&resJSON); err != nil {
return "", err return "", err
} }
return resJSON.Body, nil return strings.TrimSpace(resJSON.Body), nil
} }
+4 -16
View File
@@ -20,7 +20,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"runtime" "runtime"
"sort" "slices"
"strings" "strings"
"testing" "testing"
"time" "time"
@@ -375,7 +375,9 @@ func mergeDirectoryContents(c ...[]fileInfo) []fileInfo {
i++ i++
} }
sort.Sort(fileInfoList(res)) slices.SortFunc(res, func(a, b fileInfo) int {
return strings.Compare(a.name, b.name)
})
return res 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) 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 { func startWalker(dir string, res chan<- fileInfo, abort <-chan struct{}) chan error {
walker := func(path string, info os.FileInfo, err error) error { walker := func(path string, info os.FileInfo, err error) error {
if err != nil { if err != nil {