From 9cde068f2a49cda32bfee917110d46ba0b12d974 Mon Sep 17 00:00:00 2001 From: Tommy van der Vorst Date: Sun, 11 Aug 2024 20:20:43 +0200 Subject: [PATCH] lib/syncthing: Add wrapper for access to model (#9627) ### Purpose Wrap access to Model for users that use the syncthing Go package. See discussion: https://github.com/syncthing/syncthing/pull/9619#pullrequestreview-2212484910 ### Testing It works with the iOS app. Other than that, there are no current users of this API (to my knowledge) as Model was only exposed recently form the iOS app. --- lib/syncthing/internals.go | 86 ++++++++++++++++++++++++++++++++++++++ lib/syncthing/syncthing.go | 6 ++- 2 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 lib/syncthing/internals.go diff --git a/lib/syncthing/internals.go b/lib/syncthing/internals.go new file mode 100644 index 000000000..3fd484733 --- /dev/null +++ b/lib/syncthing/internals.go @@ -0,0 +1,86 @@ +// Copyright (C) 2024 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/. + +package syncthing + +import ( + "context" + "time" + + "github.com/syncthing/syncthing/lib/db" + "github.com/syncthing/syncthing/lib/model" + "github.com/syncthing/syncthing/lib/protocol" + "github.com/syncthing/syncthing/lib/stats" +) + +// Internals allows access to a subset of functionality in model.Model. While intended for use from applications that import +// the package, it is not intended as a stable API at this time. It does however provide a boundary between the more +// volatile Model interface and upstream users (one of which is an iOS app). +type Internals struct { + model model.Model +} + +func newInternals(model model.Model) *Internals { + return &Internals{ + model: model, + } +} + +func (m *Internals) FolderState(folderID string) (string, time.Time, error) { + return m.model.State(folderID) +} + +func (m *Internals) Ignores(folderID string) ([]string, []string, error) { + return m.model.CurrentIgnores(folderID) +} + +func (m *Internals) SetIgnores(folderID string, content []string) error { + return m.model.SetIgnores(folderID, content) +} + +func (m *Internals) DownloadBlock(ctx context.Context, deviceID protocol.DeviceID, folderID string, path string, blockNumber int, blockInfo protocol.BlockInfo, allowFromTemporary bool) ([]byte, error) { + return m.model.RequestGlobal(ctx, deviceID, folderID, path, int(blockNumber), blockInfo.Offset, blockInfo.Size, blockInfo.Hash, blockInfo.WeakHash, allowFromTemporary) +} + +func (m *Internals) BlockAvailability(folderID string, file protocol.FileInfo, block protocol.BlockInfo) ([]model.Availability, error) { + return m.model.Availability(folderID, file, block) +} + +func (m *Internals) GlobalFileInfo(folderID, path string) (protocol.FileInfo, bool, error) { + return m.model.CurrentGlobalFile(folderID, path) +} + +func (m *Internals) GlobalTree(folderID string, prefix string, levels int, returnOnlyDirectories bool) ([]*model.TreeEntry, error) { + return m.model.GlobalDirectoryTree(folderID, prefix, levels, returnOnlyDirectories) +} + +func (m *Internals) IsConnectedTo(deviceID protocol.DeviceID) bool { + return m.model.ConnectedTo(deviceID) +} + +func (m *Internals) ScanFolders() map[string]error { + return m.model.ScanFolders() +} + +func (m *Internals) Completion(deviceID protocol.DeviceID, folderID string) (model.FolderCompletion, error) { + return m.model.Completion(deviceID, folderID) +} + +func (m *Internals) DeviceStatistics() (map[protocol.DeviceID]stats.DeviceStatistics, error) { + return m.model.DeviceStatistics() +} + +func (m *Internals) PendingFolders(deviceID protocol.DeviceID) (map[string]db.PendingFolder, error) { + return m.model.PendingFolders(deviceID) +} + +func (m *Internals) DBSnapshot(folderID string) (*db.Snapshot, error) { + return m.model.DBSnapshot(folderID) +} + +func (m *Internals) ScanFolderSubdirs(folderID string, paths []string) error { + return m.model.ScanFolderSubdirs(folderID, paths) +} diff --git a/lib/syncthing/syncthing.go b/lib/syncthing/syncthing.go index 3b1a1072c..db88a0602 100644 --- a/lib/syncthing/syncthing.go +++ b/lib/syncthing/syncthing.go @@ -76,7 +76,9 @@ type App struct { stopOnce sync.Once mainServiceCancel context.CancelFunc stopped chan struct{} - Model model.Model + + // Access to internals for direct users of this package. Note that the interface in Internals is unstable! + Internals *Internals } func New(cfg config.Wrapper, dbBackend backend.Backend, evLogger events.Logger, cert tls.Certificate, opts Options) (*App, error) { @@ -244,7 +246,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.Internals = newInternals(m) a.mainService.Add(m)