mirror of
https://github.com/octoleo/syncthing.git
synced 2024-12-22 10:58:57 +00:00
all: minimal set of changes for iOS app (#9619)
### Purpose This PR contains the set of changes needed to make Syncthing work on iOS for [my iOS app for Syncthing](https://github.com/pixelspark/sushitrain). Most changes originate from [the Mobius Sync fork](http://github.com/MobiusSync/syncthing/tree/ios). I have removed the changes from their fork that are not strictly needed for my app (i.e. their changes to the GUI and command line utilities, for instance) and squashed it all in a single commit. In summary, the changes are: * Resolve non-absolute paths to the 'Documents' folder (basically the only one an app can/should write user data to by default on iOS) * Tweaking of build flags/conditions for iOS (i.e. determine which basicfs_watch, ignoreresult variant to build for iOS) * Disable upgrade mechanism on iOS * Make `RequestGlobal` and `PullerProgress` public symbols * Expose syncthing.app's Model instance (app.M) * Add no-op stub for SetLowPriority on iOS I would very much appreciate these changes to be (eventually) merged to mainline syncthing, as this would allow my iOS app to track the mainline source code directly and removes the need (for me at least) for maintaining a separate fork. Perhaps the Mobius folks can also benefit from this (although as noted this branch does not contain their changes to e.g. the GUI). ### Testing This branch has been tested with the iOS app and appears to work fine. The full set of MobiusSync changes has been used before with success. ### Screenshots n/a ### Documentation There should be no visible changes for users due to this set of changes. --------- Co-authored-by: Simon Pickup <simon@pickupinfinity.com>
This commit is contained in:
parent
e738af7c56
commit
de0b4270df
2
AUTHORS
2
AUTHORS
@ -305,6 +305,7 @@ Severin von Wnuck-Lipinski <ss7@live.de>
|
|||||||
Shaarad Dalvi <60266155+shaaraddalvi@users.noreply.github.com> <shdalv@microsoft.com>
|
Shaarad Dalvi <60266155+shaaraddalvi@users.noreply.github.com> <shdalv@microsoft.com>
|
||||||
Simon Frei (imsodin) <freisim93@gmail.com>
|
Simon Frei (imsodin) <freisim93@gmail.com>
|
||||||
Simon Mwepu <simonmwepu@gmail.com>
|
Simon Mwepu <simonmwepu@gmail.com>
|
||||||
|
Simon Pickup <simon@pickupinfinity.com>
|
||||||
Sly_tom_cat <slytomcat@mail.ru>
|
Sly_tom_cat <slytomcat@mail.ru>
|
||||||
Stefan Kuntz (Stefan-Code) <stefan.github@gmail.com> <Stefan.github@gmail.com>
|
Stefan Kuntz (Stefan-Code) <stefan.github@gmail.com> <Stefan.github@gmail.com>
|
||||||
Stefan Tatschner (rumpelsepp) <stefan@sevenbyte.org> <rumpelsepp@sevenbyte.org> <stefan@rumpelsepp.org>
|
Stefan Tatschner (rumpelsepp) <stefan@sevenbyte.org> <rumpelsepp@sevenbyte.org> <stefan@rumpelsepp.org>
|
||||||
@ -325,6 +326,7 @@ Tobias Tom (tobiastom) <t.tom@succont.de>
|
|||||||
Tom Jakubowski <tom@crystae.net>
|
Tom Jakubowski <tom@crystae.net>
|
||||||
Tomasz Wilczyński <5626656+tomasz1986@users.noreply.github.com> <twilczynski@naver.com>
|
Tomasz Wilczyński <5626656+tomasz1986@users.noreply.github.com> <twilczynski@naver.com>
|
||||||
Tommy Thorn <tommy-github-email@thorn.ws>
|
Tommy Thorn <tommy-github-email@thorn.ws>
|
||||||
|
Tommy van der Vorst <tommy-github@pixelspark.nl>
|
||||||
Tully Robinson (tojrobinson) <tully@tojr.org>
|
Tully Robinson (tojrobinson) <tully@tojr.org>
|
||||||
Tyler Brazier (tylerbrazier) <tyler@tylerbrazier.com>
|
Tyler Brazier (tylerbrazier) <tyler@tylerbrazier.com>
|
||||||
Tyler Kropp <kropptyler@gmail.com>
|
Tyler Kropp <kropptyler@gmail.com>
|
||||||
|
@ -4,10 +4,12 @@
|
|||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
// 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/.
|
// 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 !solaris cgo
|
||||||
// +build !darwin cgo
|
// +build !darwin cgo
|
||||||
|
// +build !darwin !kqueue
|
||||||
// +build !android !amd64
|
// +build !android !amd64
|
||||||
|
// +build !ios
|
||||||
|
|
||||||
package fs
|
package fs
|
||||||
|
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
// 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/.
|
// You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
//go:build darwin && !kqueue && cgo
|
//go:build darwin && !kqueue && cgo && !ios
|
||||||
// +build darwin,!kqueue,cgo
|
// +build darwin,!kqueue,cgo,!ios
|
||||||
|
|
||||||
package fs
|
package fs
|
||||||
|
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
// 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/.
|
// You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
//go: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
|
// +build !linux,!windows,!dragonfly,!freebsd,!netbsd,!openbsd,!solaris,!darwin,!cgo,!ios
|
||||||
|
|
||||||
// Catch all platforms that are not specifically handled to use the generic
|
// Catch all platforms that are not specifically handled to use the generic
|
||||||
// event types.
|
// event types.
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
// 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/.
|
// 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) || (android && amd64) || ios || (darwin && kqueue)
|
||||||
// +build solaris,!cgo darwin,!cgo android,amd64
|
// +build solaris,!cgo darwin,!cgo android,amd64 ios darwin,kqueue
|
||||||
|
|
||||||
package fs
|
package fs
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
// 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/.
|
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
//go:build windows || darwin
|
//go:build windows || darwin || ios
|
||||||
|
|
||||||
package ignoreresult
|
package ignoreresult
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
// 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/.
|
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
//go:build !windows && !darwin
|
//go:build !windows && !darwin && !ios
|
||||||
|
|
||||||
package ignoreresult
|
package ignoreresult
|
||||||
|
|
||||||
|
@ -180,7 +180,7 @@ func defaultConfigDir(userHome string) string {
|
|||||||
case build.IsWindows:
|
case build.IsWindows:
|
||||||
return windowsConfigDataDir()
|
return windowsConfigDataDir()
|
||||||
|
|
||||||
case build.IsDarwin:
|
case build.IsDarwin, build.IsIOS:
|
||||||
return darwinConfigDataDir(userHome)
|
return darwinConfigDataDir(userHome)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -191,7 +191,7 @@ func defaultConfigDir(userHome string) string {
|
|||||||
// defaultDataDir returns the default data directory, where we store the
|
// defaultDataDir returns the default data directory, where we store the
|
||||||
// database, log files, etc.
|
// database, log files, etc.
|
||||||
func defaultDataDir(userHome, configDir string) string {
|
func defaultDataDir(userHome, configDir string) string {
|
||||||
if build.IsWindows || build.IsDarwin {
|
if build.IsWindows || build.IsDarwin || build.IsIOS {
|
||||||
return configDir
|
return configDir
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1579,7 +1579,7 @@ loop:
|
|||||||
activity.using(selected)
|
activity.using(selected)
|
||||||
var buf []byte
|
var buf []byte
|
||||||
blockNo := int(state.block.Offset / int64(state.file.BlockSize()))
|
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)
|
activity.done(selected)
|
||||||
if lastError != nil {
|
if lastError != nil {
|
||||||
l.Debugln("request:", f.folderID, state.file.Name, state.block.Offset, state.block.Size, selected.ID.Short(), "returned error:", lastError)
|
l.Debugln("request:", f.folderID, state.file.Name, state.block.Offset, state.block.Size, selected.ID.Short(), "returned error:", lastError)
|
||||||
|
@ -261,7 +261,7 @@ func (c *folderSummaryService) processUpdate(ev events.Event) {
|
|||||||
return
|
return
|
||||||
|
|
||||||
case events.DownloadProgress:
|
case events.DownloadProgress:
|
||||||
data := ev.Data.(map[string]map[string]*pullerProgress)
|
data := ev.Data.(map[string]map[string]*PullerProgress)
|
||||||
c.foldersMut.Lock()
|
c.foldersMut.Lock()
|
||||||
for folder := range data {
|
for folder := range data {
|
||||||
c.folders[folder] = struct{}{}
|
c.folders[folder] = struct{}{}
|
||||||
|
@ -435,6 +435,28 @@ type Model struct {
|
|||||||
result1 protocol.RequestResponse
|
result1 protocol.RequestResponse
|
||||||
result2 error
|
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
|
ResetFolderStub func(string) error
|
||||||
resetFolderMutex sync.RWMutex
|
resetFolderMutex sync.RWMutex
|
||||||
resetFolderArgsForCall []struct {
|
resetFolderArgsForCall []struct {
|
||||||
@ -2558,6 +2580,84 @@ func (fake *Model) RequestReturnsOnCall(i int, result1 protocol.RequestResponse,
|
|||||||
}{result1, result2}
|
}{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 {
|
func (fake *Model) ResetFolder(arg1 string) error {
|
||||||
fake.resetFolderMutex.Lock()
|
fake.resetFolderMutex.Lock()
|
||||||
ret, specificReturn := fake.resetFolderReturnsOnCall[len(fake.resetFolderArgsForCall)]
|
ret, specificReturn := fake.resetFolderReturnsOnCall[len(fake.resetFolderArgsForCall)]
|
||||||
@ -3258,6 +3358,8 @@ func (fake *Model) Invocations() map[string][][]interface{} {
|
|||||||
defer fake.remoteNeedFolderFilesMutex.RUnlock()
|
defer fake.remoteNeedFolderFilesMutex.RUnlock()
|
||||||
fake.requestMutex.RLock()
|
fake.requestMutex.RLock()
|
||||||
defer fake.requestMutex.RUnlock()
|
defer fake.requestMutex.RUnlock()
|
||||||
|
fake.requestGlobalMutex.RLock()
|
||||||
|
defer fake.requestGlobalMutex.RUnlock()
|
||||||
fake.resetFolderMutex.RLock()
|
fake.resetFolderMutex.RLock()
|
||||||
defer fake.resetFolderMutex.RUnlock()
|
defer fake.resetFolderMutex.RUnlock()
|
||||||
fake.restoreFolderVersionsMutex.RLock()
|
fake.restoreFolderVersionsMutex.RLock()
|
||||||
|
@ -117,6 +117,8 @@ type Model interface {
|
|||||||
DismissPendingFolder(device protocol.DeviceID, folder string) error
|
DismissPendingFolder(device protocol.DeviceID, folder string) error
|
||||||
|
|
||||||
GlobalDirectoryTree(folder, prefix string, levels int, dirsOnly bool) ([]*TreeEntry, 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 {
|
type model struct {
|
||||||
@ -375,7 +377,7 @@ func (m *model) addAndStartFolderLockedWithIgnores(cfg config.FolderConfiguratio
|
|||||||
// it'll show up as errored later.
|
// it'll show up as errored later.
|
||||||
|
|
||||||
if err := cfg.CreateRoot(); err != nil {
|
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 {
|
} else if err = cfg.CreateMarker(); err != nil {
|
||||||
l.Warnln("Failed to create folder marker:", err)
|
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)
|
conn, connOK := m.requestConnectionForDevice(deviceID)
|
||||||
if !connOK {
|
if !connOK {
|
||||||
return nil, fmt.Errorf("requestGlobal: no connection to device: %s", deviceID.Short())
|
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
|
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
|
// Interactive operating systems; don't load the system too heavily by
|
||||||
// default.
|
// default.
|
||||||
return 1
|
return 1
|
||||||
|
@ -222,7 +222,7 @@ func BenchmarkRequestOut(b *testing.B) {
|
|||||||
|
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
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 {
|
if err != nil {
|
||||||
b.Error(err)
|
b.Error(err)
|
||||||
}
|
}
|
||||||
|
@ -118,12 +118,12 @@ func (t *ProgressEmitter) Serve(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *ProgressEmitter) sendDownloadProgressEventLocked() {
|
func (t *ProgressEmitter) sendDownloadProgressEventLocked() {
|
||||||
output := make(map[string]map[string]*pullerProgress)
|
output := make(map[string]map[string]*PullerProgress)
|
||||||
for folder, pullers := range t.registry {
|
for folder, pullers := range t.registry {
|
||||||
if len(pullers) == 0 {
|
if len(pullers) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
output[folder] = make(map[string]*pullerProgress)
|
output[folder] = make(map[string]*PullerProgress)
|
||||||
for name, puller := range pullers {
|
for name, puller := range pullers {
|
||||||
output[folder][name] = puller.Progress()
|
output[folder][name] = puller.Progress()
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ func expectEvent(w events.Subscription, t *testing.T, size int) {
|
|||||||
if event.Type != events.DownloadProgress {
|
if event.Type != events.DownloadProgress {
|
||||||
t.Fatal("Unexpected event:", event, "at", caller(1))
|
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 {
|
if len(data) != size {
|
||||||
t.Fatal("Unexpected event data size:", data, "at", caller(1))
|
t.Fatal("Unexpected event data size:", data, "at", caller(1))
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@ func newSharedPullerState(file protocol.FileInfo, fs fs.Filesystem, folderID, te
|
|||||||
}
|
}
|
||||||
|
|
||||||
// A momentary state representing the progress of the puller
|
// A momentary state representing the progress of the puller
|
||||||
type pullerProgress struct {
|
type PullerProgress struct {
|
||||||
Total int `json:"total"`
|
Total int `json:"total"`
|
||||||
Reused int `json:"reused"`
|
Reused int `json:"reused"`
|
||||||
CopiedFromOrigin int `json:"copiedFromOrigin"`
|
CopiedFromOrigin int `json:"copiedFromOrigin"`
|
||||||
@ -405,13 +405,13 @@ func encryptionTrailerSize(file protocol.FileInfo) int64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Progress returns the momentarily progress for the puller
|
// Progress returns the momentarily progress for the puller
|
||||||
func (s *sharedPullerState) Progress() *pullerProgress {
|
func (s *sharedPullerState) Progress() *PullerProgress {
|
||||||
s.mut.RLock()
|
s.mut.RLock()
|
||||||
defer s.mut.RUnlock()
|
defer s.mut.RUnlock()
|
||||||
total := s.reused + s.copyTotal + s.pullTotal
|
total := s.reused + s.copyTotal + s.pullTotal
|
||||||
done := total - s.copyNeeded - s.pullNeeded
|
done := total - s.copyNeeded - s.pullNeeded
|
||||||
file := len(s.file.Blocks)
|
file := len(s.file.Blocks)
|
||||||
return &pullerProgress{
|
return &PullerProgress{
|
||||||
Total: total,
|
Total: total,
|
||||||
Reused: s.reused,
|
Reused: s.reused,
|
||||||
CopiedFromOrigin: s.copyOrigin,
|
CopiedFromOrigin: s.copyOrigin,
|
||||||
|
16
lib/osutil/lowprio_noop.go
Normal file
16
lib/osutil/lowprio_noop.go
Normal file
@ -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
|
||||||
|
}
|
@ -4,8 +4,8 @@
|
|||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
// 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/.
|
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
//go:build (!windows && !linux) || android
|
//go:build (!windows && !linux && !ios) || android
|
||||||
// +build !windows,!linux android
|
// +build !windows,!linux,!ios android
|
||||||
|
|
||||||
package osutil
|
package osutil
|
||||||
|
|
||||||
|
@ -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
|
// normalizePath returns the normalized relative path (possibly after fixing
|
||||||
// it on disk), or skip is true.
|
// it on disk), or skip is true.
|
||||||
func (w *walker) normalizePath(path string, info fs.FileInfo) (normPath string, err error) {
|
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.
|
// Mac OS X file names should always be NFD normalized.
|
||||||
normPath = norm.NFD.String(path)
|
normPath = norm.NFD.String(path)
|
||||||
} else {
|
} else {
|
||||||
|
@ -77,6 +77,7 @@ type App struct {
|
|||||||
stopOnce sync.Once
|
stopOnce sync.Once
|
||||||
mainServiceCancel context.CancelFunc
|
mainServiceCancel context.CancelFunc
|
||||||
stopped chan struct{}
|
stopped chan struct{}
|
||||||
|
Model model.Model
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(cfg config.Wrapper, dbBackend backend.Backend, evLogger events.Logger, cert tls.Certificate, opts Options) (*App, error) {
|
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()
|
keyGen := protocol.NewKeyGenerator()
|
||||||
m := model.NewModel(a.cfg, a.myID, a.ll, protectedFiles, a.evLogger, keyGen)
|
m := model.NewModel(a.cfg, a.myID, a.ll, protectedFiles, a.evLogger, keyGen)
|
||||||
|
a.Model = m
|
||||||
|
|
||||||
a.mainService.Add(m)
|
a.mainService.Add(m)
|
||||||
|
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
// 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/.
|
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
//go:build !noupgrade
|
//go:build !noupgrade && !ios
|
||||||
// +build !noupgrade
|
// +build !noupgrade,!ios
|
||||||
|
|
||||||
package upgrade
|
package upgrade
|
||||||
|
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
// 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/.
|
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
//go:build noupgrade
|
//go:build noupgrade || ios
|
||||||
// +build noupgrade
|
// +build noupgrade ios
|
||||||
|
|
||||||
package upgrade
|
package upgrade
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user