浏览代码

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
Jakob Borg 4 月之前
父节点
当前提交
bb91f53641

+ 3 - 0
.github/workflows/build-syncthing.yaml

@@ -3,6 +3,9 @@ name: Build Syncthing
 on:
   pull_request:
   push:
+    branches-ignore:
+      - release
+      - release-rc*
   workflow_call:
   workflow_dispatch:
 

+ 4 - 2
cmd/syncthing/crash_reporting.go

@@ -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

+ 2 - 2
lib/api/tokenmanager.go

@@ -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] {

+ 2 - 3
lib/config/config.go

@@ -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

+ 3 - 3
lib/config/deviceconfiguration.go

@@ -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
 }

+ 3 - 3
lib/config/folderconfiguration.go

@@ -15,7 +15,7 @@ import (
 	"fmt"
 	"path"
 	"path/filepath"
-	"sort"
+	"slices"
 	"strings"
 	"time"
 
@@ -288,8 +288,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
lib/model/blockpullreorderer.go

@@ -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

+ 3 - 3
lib/model/blockpullreorderer_test.go

@@ -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
lib/model/folder.go

@@ -13,7 +13,7 @@ import (
 	"math/rand"
 	"path/filepath"
 	"slices"
-	"sort"
+	"strings"
 	"time"
 
 	"github.com/syncthing/syncthing/internal/db"
@@ -1226,7 +1226,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
 }
 

+ 5 - 2
lib/model/folder_recvenc.go

@@ -8,7 +8,8 @@ package model
 
 import (
 	"fmt"
-	"sort"
+	"slices"
+	"strings"
 
 	"github.com/syncthing/syncthing/internal/itererr"
 	"github.com/syncthing/syncthing/lib/config"
@@ -104,7 +105,9 @@ func (f *receiveEncryptedFolder) revertHandleDirs(dirs []string) {
 	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, scanChan); err != nil {
 			f.newScanError(dir, fmt.Errorf("deleting unexpected dir: %w", err))

+ 5 - 2
lib/model/folder_recvonly.go

@@ -7,7 +7,8 @@
 package model
 
 import (
-	"sort"
+	"slices"
+	"strings"
 	"time"
 
 	"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) {
 	// 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

+ 4 - 16
lib/model/folder_sendrecv.go

@@ -14,7 +14,7 @@ import (
 	"fmt"
 	"io"
 	"path/filepath"
-	"sort"
+	"slices"
 	"strconv"
 	"strings"
 	"time"
@@ -1854,7 +1854,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)
@@ -2196,20 +2198,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

+ 7 - 14
lib/scanner/walk_test.go

@@ -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)

+ 5 - 2
lib/versioner/empty_dir_tracker.go

@@ -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
 }
 

+ 3 - 0
relnotes/README.md

@@ -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.

+ 5 - 0
script/authors.go

@@ -99,6 +99,11 @@ func main() {
 
 	// 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")
 	if err != nil {
 		log.Fatal(err)

+ 21 - 12
script/relnotes.go

@@ -43,29 +43,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 +114,5 @@ 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(resJSON.Body), nil
 }

+ 4 - 16
test/util.go

@@ -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 {