diff --git a/AUTHORS b/AUTHORS index 533dc4096..a63609d71 100644 --- a/AUTHORS +++ b/AUTHORS @@ -305,6 +305,7 @@ Severin von Wnuck-Lipinski Shaarad Dalvi <60266155+shaaraddalvi@users.noreply.github.com> Simon Frei (imsodin) Simon Mwepu +Simon Pickup Sly_tom_cat Stefan Kuntz (Stefan-Code) Stefan Tatschner (rumpelsepp) @@ -325,6 +326,7 @@ Tobias Tom (tobiastom) Tom Jakubowski Tomasz WilczyƄski <5626656+tomasz1986@users.noreply.github.com> Tommy Thorn +Tommy van der Vorst Tully Robinson (tojrobinson) Tyler Brazier (tylerbrazier) Tyler Kropp diff --git a/lib/fs/basicfs_watch.go b/lib/fs/basicfs_watch.go index c65529cc5..ab275270a 100644 --- a/lib/fs/basicfs_watch.go +++ b/lib/fs/basicfs_watch.go @@ -4,10 +4,12 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this file, // You can obtain one at http://mozilla.org/MPL/2.0/. -//go:build !(solaris && !cgo) && !(darwin && !cgo) && !(android && amd64) +//go:build !(solaris && !cgo) && !(darwin && !cgo) && !(darwin && kqueue) && !(android && amd64) && !ios // +build !solaris cgo // +build !darwin cgo +// +build !darwin !kqueue // +build !android !amd64 +// +build !ios package fs diff --git a/lib/fs/basicfs_watch_eventtypes_darwin.go b/lib/fs/basicfs_watch_eventtypes_darwin.go index f7ca0e008..e8fa49a08 100644 --- a/lib/fs/basicfs_watch_eventtypes_darwin.go +++ b/lib/fs/basicfs_watch_eventtypes_darwin.go @@ -4,8 +4,8 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this file, // You can obtain one at http://mozilla.org/MPL/2.0/. -//go:build darwin && !kqueue && cgo -// +build darwin,!kqueue,cgo +//go:build darwin && !kqueue && cgo && !ios +// +build darwin,!kqueue,cgo,!ios package fs diff --git a/lib/fs/basicfs_watch_eventtypes_other.go b/lib/fs/basicfs_watch_eventtypes_other.go index beb38e7db..cf08856f7 100644 --- a/lib/fs/basicfs_watch_eventtypes_other.go +++ b/lib/fs/basicfs_watch_eventtypes_other.go @@ -4,8 +4,8 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this file, // You can obtain one at http://mozilla.org/MPL/2.0/. -//go:build !linux && !windows && !dragonfly && !freebsd && !netbsd && !openbsd && !solaris && !darwin && !cgo -// +build !linux,!windows,!dragonfly,!freebsd,!netbsd,!openbsd,!solaris,!darwin,!cgo +//go:build !linux && !windows && !dragonfly && !freebsd && !netbsd && !openbsd && !solaris && !darwin && !cgo && !ios +// +build !linux,!windows,!dragonfly,!freebsd,!netbsd,!openbsd,!solaris,!darwin,!cgo,!ios // Catch all platforms that are not specifically handled to use the generic // event types. diff --git a/lib/fs/basicfs_watch_unsupported.go b/lib/fs/basicfs_watch_unsupported.go index fa4ab80da..4d10dc71a 100644 --- a/lib/fs/basicfs_watch_unsupported.go +++ b/lib/fs/basicfs_watch_unsupported.go @@ -4,8 +4,8 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this file, // You can obtain one at http://mozilla.org/MPL/2.0/. -//go:build (solaris && !cgo) || (darwin && !cgo) || (android && amd64) -// +build solaris,!cgo darwin,!cgo android,amd64 +//go:build (solaris && !cgo) || (darwin && !cgo) || (android && amd64) || ios || (darwin && kqueue) +// +build solaris,!cgo darwin,!cgo android,amd64 ios darwin,kqueue package fs diff --git a/lib/ignore/ignoreresult/ignoreresult_foldcase.go b/lib/ignore/ignoreresult/ignoreresult_foldcase.go index a77f13329..ebb8d92a4 100644 --- a/lib/ignore/ignoreresult/ignoreresult_foldcase.go +++ b/lib/ignore/ignoreresult/ignoreresult_foldcase.go @@ -4,7 +4,7 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this file, // You can obtain one at https://mozilla.org/MPL/2.0/. -//go:build windows || darwin +//go:build windows || darwin || ios package ignoreresult diff --git a/lib/ignore/ignoreresult/ignoreresult_nofoldcase.go b/lib/ignore/ignoreresult/ignoreresult_nofoldcase.go index 55c7d23d5..714820e63 100644 --- a/lib/ignore/ignoreresult/ignoreresult_nofoldcase.go +++ b/lib/ignore/ignoreresult/ignoreresult_nofoldcase.go @@ -4,7 +4,7 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this file, // You can obtain one at https://mozilla.org/MPL/2.0/. -//go:build !windows && !darwin +//go:build !windows && !darwin && !ios package ignoreresult diff --git a/lib/locations/locations.go b/lib/locations/locations.go index ad92124a6..197c686eb 100644 --- a/lib/locations/locations.go +++ b/lib/locations/locations.go @@ -180,7 +180,7 @@ func defaultConfigDir(userHome string) string { case build.IsWindows: return windowsConfigDataDir() - case build.IsDarwin: + case build.IsDarwin, build.IsIOS: return darwinConfigDataDir(userHome) default: @@ -191,7 +191,7 @@ func defaultConfigDir(userHome string) string { // defaultDataDir returns the default data directory, where we store the // database, log files, etc. func defaultDataDir(userHome, configDir string) string { - if build.IsWindows || build.IsDarwin { + if build.IsWindows || build.IsDarwin || build.IsIOS { return configDir } diff --git a/lib/model/folder_sendrecv.go b/lib/model/folder_sendrecv.go index 2b77b67f0..7e8639af1 100644 --- a/lib/model/folder_sendrecv.go +++ b/lib/model/folder_sendrecv.go @@ -1579,7 +1579,7 @@ loop: activity.using(selected) var buf []byte blockNo := int(state.block.Offset / int64(state.file.BlockSize())) - buf, lastError = f.model.requestGlobal(f.ctx, selected.ID, f.folderID, state.file.Name, blockNo, state.block.Offset, int(state.block.Size), state.block.Hash, state.block.WeakHash, selected.FromTemporary) + buf, lastError = f.model.RequestGlobal(f.ctx, selected.ID, f.folderID, state.file.Name, blockNo, state.block.Offset, int(state.block.Size), state.block.Hash, state.block.WeakHash, selected.FromTemporary) activity.done(selected) if lastError != nil { l.Debugln("request:", f.folderID, state.file.Name, state.block.Offset, state.block.Size, selected.ID.Short(), "returned error:", lastError) diff --git a/lib/model/folder_summary.go b/lib/model/folder_summary.go index 95653c1de..b1d1e77d8 100644 --- a/lib/model/folder_summary.go +++ b/lib/model/folder_summary.go @@ -261,7 +261,7 @@ func (c *folderSummaryService) processUpdate(ev events.Event) { return case events.DownloadProgress: - data := ev.Data.(map[string]map[string]*pullerProgress) + data := ev.Data.(map[string]map[string]*PullerProgress) c.foldersMut.Lock() for folder := range data { c.folders[folder] = struct{}{} diff --git a/lib/model/mocks/model.go b/lib/model/mocks/model.go index 2049b6567..52c28df53 100644 --- a/lib/model/mocks/model.go +++ b/lib/model/mocks/model.go @@ -435,6 +435,28 @@ type Model struct { result1 protocol.RequestResponse result2 error } + RequestGlobalStub func(context.Context, protocol.DeviceID, string, string, int, int64, int, []byte, uint32, bool) ([]byte, error) + requestGlobalMutex sync.RWMutex + requestGlobalArgsForCall []struct { + arg1 context.Context + arg2 protocol.DeviceID + arg3 string + arg4 string + arg5 int + arg6 int64 + arg7 int + arg8 []byte + arg9 uint32 + arg10 bool + } + requestGlobalReturns struct { + result1 []byte + result2 error + } + requestGlobalReturnsOnCall map[int]struct { + result1 []byte + result2 error + } ResetFolderStub func(string) error resetFolderMutex sync.RWMutex resetFolderArgsForCall []struct { @@ -2558,6 +2580,84 @@ func (fake *Model) RequestReturnsOnCall(i int, result1 protocol.RequestResponse, }{result1, result2} } +func (fake *Model) RequestGlobal(arg1 context.Context, arg2 protocol.DeviceID, arg3 string, arg4 string, arg5 int, arg6 int64, arg7 int, arg8 []byte, arg9 uint32, arg10 bool) ([]byte, error) { + var arg8Copy []byte + if arg8 != nil { + arg8Copy = make([]byte, len(arg8)) + copy(arg8Copy, arg8) + } + fake.requestGlobalMutex.Lock() + ret, specificReturn := fake.requestGlobalReturnsOnCall[len(fake.requestGlobalArgsForCall)] + fake.requestGlobalArgsForCall = append(fake.requestGlobalArgsForCall, struct { + arg1 context.Context + arg2 protocol.DeviceID + arg3 string + arg4 string + arg5 int + arg6 int64 + arg7 int + arg8 []byte + arg9 uint32 + arg10 bool + }{arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8Copy, arg9, arg10}) + stub := fake.RequestGlobalStub + fakeReturns := fake.requestGlobalReturns + fake.recordInvocation("RequestGlobal", []interface{}{arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8Copy, arg9, arg10}) + fake.requestGlobalMutex.Unlock() + if stub != nil { + return stub(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) + } + if specificReturn { + return ret.result1, ret.result2 + } + return fakeReturns.result1, fakeReturns.result2 +} + +func (fake *Model) RequestGlobalCallCount() int { + fake.requestGlobalMutex.RLock() + defer fake.requestGlobalMutex.RUnlock() + return len(fake.requestGlobalArgsForCall) +} + +func (fake *Model) RequestGlobalCalls(stub func(context.Context, protocol.DeviceID, string, string, int, int64, int, []byte, uint32, bool) ([]byte, error)) { + fake.requestGlobalMutex.Lock() + defer fake.requestGlobalMutex.Unlock() + fake.RequestGlobalStub = stub +} + +func (fake *Model) RequestGlobalArgsForCall(i int) (context.Context, protocol.DeviceID, string, string, int, int64, int, []byte, uint32, bool) { + fake.requestGlobalMutex.RLock() + defer fake.requestGlobalMutex.RUnlock() + argsForCall := fake.requestGlobalArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3, argsForCall.arg4, argsForCall.arg5, argsForCall.arg6, argsForCall.arg7, argsForCall.arg8, argsForCall.arg9, argsForCall.arg10 +} + +func (fake *Model) RequestGlobalReturns(result1 []byte, result2 error) { + fake.requestGlobalMutex.Lock() + defer fake.requestGlobalMutex.Unlock() + fake.RequestGlobalStub = nil + fake.requestGlobalReturns = struct { + result1 []byte + result2 error + }{result1, result2} +} + +func (fake *Model) RequestGlobalReturnsOnCall(i int, result1 []byte, result2 error) { + fake.requestGlobalMutex.Lock() + defer fake.requestGlobalMutex.Unlock() + fake.RequestGlobalStub = nil + if fake.requestGlobalReturnsOnCall == nil { + fake.requestGlobalReturnsOnCall = make(map[int]struct { + result1 []byte + result2 error + }) + } + fake.requestGlobalReturnsOnCall[i] = struct { + result1 []byte + result2 error + }{result1, result2} +} + func (fake *Model) ResetFolder(arg1 string) error { fake.resetFolderMutex.Lock() ret, specificReturn := fake.resetFolderReturnsOnCall[len(fake.resetFolderArgsForCall)] @@ -3258,6 +3358,8 @@ func (fake *Model) Invocations() map[string][][]interface{} { defer fake.remoteNeedFolderFilesMutex.RUnlock() fake.requestMutex.RLock() defer fake.requestMutex.RUnlock() + fake.requestGlobalMutex.RLock() + defer fake.requestGlobalMutex.RUnlock() fake.resetFolderMutex.RLock() defer fake.resetFolderMutex.RUnlock() fake.restoreFolderVersionsMutex.RLock() diff --git a/lib/model/model.go b/lib/model/model.go index f88118eb9..dab7b0575 100644 --- a/lib/model/model.go +++ b/lib/model/model.go @@ -117,6 +117,8 @@ type Model interface { DismissPendingFolder(device protocol.DeviceID, folder string) error GlobalDirectoryTree(folder, prefix string, levels int, dirsOnly bool) ([]*TreeEntry, error) + + RequestGlobal(ctx context.Context, deviceID protocol.DeviceID, folder, name string, blockNo int, offset int64, size int, hash []byte, weakHash uint32, fromTemporary bool) ([]byte, error) } type model struct { @@ -375,7 +377,7 @@ func (m *model) addAndStartFolderLockedWithIgnores(cfg config.FolderConfiguratio // it'll show up as errored later. if err := cfg.CreateRoot(); err != nil { - l.Warnln("Failed to create folder root directory", err) + l.Warnln("Failed to create folder root directory:", err) } else if err = cfg.CreateMarker(); err != nil { l.Warnln("Failed to create folder marker:", err) } @@ -2460,7 +2462,7 @@ func (m *model) deviceDidCloseRLocked(deviceID protocol.DeviceID, duration time. } } -func (m *model) requestGlobal(ctx context.Context, deviceID protocol.DeviceID, folder, name string, blockNo int, offset int64, size int, hash []byte, weakHash uint32, fromTemporary bool) ([]byte, error) { +func (m *model) RequestGlobal(ctx context.Context, deviceID protocol.DeviceID, folder, name string, blockNo int, offset int64, size int, hash []byte, weakHash uint32, fromTemporary bool) ([]byte, error) { conn, connOK := m.requestConnectionForDevice(deviceID) if !connOK { return nil, fmt.Errorf("requestGlobal: no connection to device: %s", deviceID.Short()) @@ -2566,7 +2568,7 @@ func (m *model) numHashers(folder string) int { return folderCfg.Hashers } - if build.IsWindows || build.IsDarwin || build.IsAndroid { + if build.IsWindows || build.IsDarwin || build.IsIOS || build.IsAndroid { // Interactive operating systems; don't load the system too heavily by // default. return 1 diff --git a/lib/model/model_test.go b/lib/model/model_test.go index 0032790af..60b25cd22 100644 --- a/lib/model/model_test.go +++ b/lib/model/model_test.go @@ -222,7 +222,7 @@ func BenchmarkRequestOut(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { - data, err := m.requestGlobal(context.Background(), device1, "default", files[i%n].Name, 0, 0, 32, nil, 0, false) + data, err := m.RequestGlobal(context.Background(), device1, "default", files[i%n].Name, 0, 0, 32, nil, 0, false) if err != nil { b.Error(err) } diff --git a/lib/model/progressemitter.go b/lib/model/progressemitter.go index 537f6b561..86b56c1d7 100644 --- a/lib/model/progressemitter.go +++ b/lib/model/progressemitter.go @@ -118,12 +118,12 @@ func (t *ProgressEmitter) Serve(ctx context.Context) error { } func (t *ProgressEmitter) sendDownloadProgressEventLocked() { - output := make(map[string]map[string]*pullerProgress) + output := make(map[string]map[string]*PullerProgress) for folder, pullers := range t.registry { if len(pullers) == 0 { continue } - output[folder] = make(map[string]*pullerProgress) + output[folder] = make(map[string]*PullerProgress) for name, puller := range pullers { output[folder][name] = puller.Progress() } diff --git a/lib/model/progressemitter_test.go b/lib/model/progressemitter_test.go index 62d980f8c..bac8dff7a 100644 --- a/lib/model/progressemitter_test.go +++ b/lib/model/progressemitter_test.go @@ -39,7 +39,7 @@ func expectEvent(w events.Subscription, t *testing.T, size int) { if event.Type != events.DownloadProgress { t.Fatal("Unexpected event:", event, "at", caller(1)) } - data := event.Data.(map[string]map[string]*pullerProgress) + data := event.Data.(map[string]map[string]*PullerProgress) if len(data) != size { t.Fatal("Unexpected event data size:", data, "at", caller(1)) } diff --git a/lib/model/sharedpullerstate.go b/lib/model/sharedpullerstate.go index 6679909ba..384d05d6c 100644 --- a/lib/model/sharedpullerstate.go +++ b/lib/model/sharedpullerstate.go @@ -75,7 +75,7 @@ func newSharedPullerState(file protocol.FileInfo, fs fs.Filesystem, folderID, te } // A momentary state representing the progress of the puller -type pullerProgress struct { +type PullerProgress struct { Total int `json:"total"` Reused int `json:"reused"` CopiedFromOrigin int `json:"copiedFromOrigin"` @@ -405,13 +405,13 @@ func encryptionTrailerSize(file protocol.FileInfo) int64 { } // Progress returns the momentarily progress for the puller -func (s *sharedPullerState) Progress() *pullerProgress { +func (s *sharedPullerState) Progress() *PullerProgress { s.mut.RLock() defer s.mut.RUnlock() total := s.reused + s.copyTotal + s.pullTotal done := total - s.copyNeeded - s.pullNeeded file := len(s.file.Blocks) - return &pullerProgress{ + return &PullerProgress{ Total: total, Reused: s.reused, CopiedFromOrigin: s.copyOrigin, diff --git a/lib/osutil/lowprio_noop.go b/lib/osutil/lowprio_noop.go new file mode 100644 index 000000000..41f275744 --- /dev/null +++ b/lib/osutil/lowprio_noop.go @@ -0,0 +1,16 @@ +// Copyright (C) 2020 The Syncthing Authors. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +//go:build ios +// +build ios + +package osutil + +// SetLowPriority not possible on some platforms +// I/O priority depending on the platform and OS. +func SetLowPriority() error { + return nil +} diff --git a/lib/osutil/lowprio_unix.go b/lib/osutil/lowprio_unix.go index d0885b861..deb7d2342 100644 --- a/lib/osutil/lowprio_unix.go +++ b/lib/osutil/lowprio_unix.go @@ -4,8 +4,8 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this file, // You can obtain one at https://mozilla.org/MPL/2.0/. -//go:build (!windows && !linux) || android -// +build !windows,!linux android +//go:build (!windows && !linux && !ios) || android +// +build !windows,!linux,!ios android package osutil diff --git a/lib/scanner/walk.go b/lib/scanner/walk.go index 2397444b4..3c34ca285 100644 --- a/lib/scanner/walk.go +++ b/lib/scanner/walk.go @@ -553,7 +553,7 @@ func (w *walker) walkSymlink(ctx context.Context, relPath string, info fs.FileIn // normalizePath returns the normalized relative path (possibly after fixing // it on disk), or skip is true. func (w *walker) normalizePath(path string, info fs.FileInfo) (normPath string, err error) { - if build.IsDarwin { + if build.IsDarwin || build.IsIOS { // Mac OS X file names should always be NFD normalized. normPath = norm.NFD.String(path) } else { diff --git a/lib/syncthing/syncthing.go b/lib/syncthing/syncthing.go index fd627b581..a97abba6b 100644 --- a/lib/syncthing/syncthing.go +++ b/lib/syncthing/syncthing.go @@ -77,6 +77,7 @@ type App struct { stopOnce sync.Once mainServiceCancel context.CancelFunc stopped chan struct{} + Model model.Model } func New(cfg config.Wrapper, dbBackend backend.Backend, evLogger events.Logger, cert tls.Certificate, opts Options) (*App, error) { @@ -249,6 +250,7 @@ func (a *App) startup() error { keyGen := protocol.NewKeyGenerator() m := model.NewModel(a.cfg, a.myID, a.ll, protectedFiles, a.evLogger, keyGen) + a.Model = m a.mainService.Add(m) diff --git a/lib/upgrade/upgrade_supported.go b/lib/upgrade/upgrade_supported.go index b43654d7e..35b5f540d 100644 --- a/lib/upgrade/upgrade_supported.go +++ b/lib/upgrade/upgrade_supported.go @@ -4,8 +4,8 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this file, // You can obtain one at https://mozilla.org/MPL/2.0/. -//go:build !noupgrade -// +build !noupgrade +//go:build !noupgrade && !ios +// +build !noupgrade,!ios package upgrade diff --git a/lib/upgrade/upgrade_unsupp.go b/lib/upgrade/upgrade_unsupp.go index b442024d2..f8d922279 100644 --- a/lib/upgrade/upgrade_unsupp.go +++ b/lib/upgrade/upgrade_unsupp.go @@ -4,8 +4,8 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this file, // You can obtain one at https://mozilla.org/MPL/2.0/. -//go:build noupgrade -// +build noupgrade +//go:build noupgrade || ios +// +build noupgrade ios package upgrade