From f9007ed106762a9b83e37495df748951e5dc3345 Mon Sep 17 00:00:00 2001 From: Jakob Borg Date: Tue, 1 Apr 2025 23:51:37 -0700 Subject: [PATCH 1/2] build(deps): update dependencies (#10020) deps deps deps --- go.mod | 14 +++++++------- go.sum | 28 ++++++++++++++-------------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/go.mod b/go.mod index f2ce0ee4d..7f58e1b5f 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.23.0 require ( github.com/AudriusButkevicius/recli v0.0.7-0.20220911121932-d000ce8fbf0f - github.com/alecthomas/kong v1.9.0 + github.com/alecthomas/kong v1.10.0 github.com/aws/aws-sdk-go v1.55.6 github.com/calmh/incontainer v1.0.0 github.com/calmh/xdr v1.2.0 @@ -21,7 +21,7 @@ require ( github.com/jackpal/go-nat-pmp v1.0.2 github.com/julienschmidt/httprouter v1.3.0 github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 - github.com/maruel/panicparse/v2 v2.4.0 + github.com/maruel/panicparse/v2 v2.5.0 github.com/maxbrunsfeld/counterfeiter/v6 v6.11.2 github.com/maxmind/geoipupdate/v6 v6.1.0 github.com/miscreant/miscreant.go v0.0.0-20200214223636-26d376326b75 @@ -29,10 +29,10 @@ require ( github.com/pierrec/lz4/v4 v4.1.22 github.com/prometheus/client_golang v1.21.1 github.com/puzpuzpuz/xsync/v3 v3.5.1 - github.com/quic-go/quic-go v0.50.0 + github.com/quic-go/quic-go v0.50.1 github.com/rabbitmq/amqp091-go v1.10.0 - github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 - github.com/shirou/gopsutil/v4 v4.25.2 + github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9 + github.com/shirou/gopsutil/v4 v4.25.3 github.com/syncthing/notify v0.0.0-20250207082249-f0fa8f99c2bc github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d github.com/thejerf/suture/v4 v4.0.6 @@ -41,12 +41,12 @@ require ( github.com/willabides/kongplete v0.4.0 go.uber.org/automaxprocs v1.6.0 golang.org/x/crypto v0.36.0 - golang.org/x/net v0.37.0 + golang.org/x/net v0.38.0 golang.org/x/sys v0.31.0 golang.org/x/text v0.23.0 golang.org/x/time v0.11.0 golang.org/x/tools v0.31.0 - google.golang.org/protobuf v1.36.5 + google.golang.org/protobuf v1.36.6 sigs.k8s.io/yaml v1.4.0 ) diff --git a/go.sum b/go.sum index bd69955ed..7b79f6510 100644 --- a/go.sum +++ b/go.sum @@ -5,8 +5,8 @@ github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzS github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= -github.com/alecthomas/kong v1.9.0 h1:Wgg0ll5Ys7xDnpgYBuBn/wPeLGAuK0NvYmEcisJgrIs= -github.com/alecthomas/kong v1.9.0/go.mod h1:p2vqieVMeTAnaC83txKtXe8FLke2X07aruPWXyMPQrU= +github.com/alecthomas/kong v1.10.0 h1:8K4rGDpT7Iu+jEXCIJUeKqvpwZHbsFRoebLbnzlmrpw= +github.com/alecthomas/kong v1.10.0/go.mod h1:p2vqieVMeTAnaC83txKtXe8FLke2X07aruPWXyMPQrU= github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa h1:LHTHcTQiSGT7VVbI0o4wBRNQIgn917usHWOd6VAffYI= @@ -142,8 +142,8 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 h1:7UMa6KCCMjZEMDtTVdcGu0B1GmmC7QJKiCCjyTAWQy0= github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k= -github.com/maruel/panicparse/v2 v2.4.0 h1:yQKMIbQ0DKfinzVkTkcUzQyQ60UCiNnYfR7PWwTs2VI= -github.com/maruel/panicparse/v2 v2.4.0/go.mod h1:nOY2OKe8csO3F3SA5+hsxot05JLgukrF54B9x88fVp4= +github.com/maruel/panicparse/v2 v2.5.0 h1:yCtuS0FWjfd0RTYMXGpDvWcb0kINm8xJGu18/xMUh00= +github.com/maruel/panicparse/v2 v2.5.0/go.mod h1:DA2fDiBk63bKfBf4CVZP9gb4fuvzdPbLDsSI873hweQ= github.com/maxbrunsfeld/counterfeiter/v6 v6.11.2 h1:yVCLo4+ACVroOEr4iFU1iH46Ldlzz2rTuu18Ra7M8sU= github.com/maxbrunsfeld/counterfeiter/v6 v6.11.2/go.mod h1:VzB2VoMh1Y32/QqDfg9ZJYHj99oM4LiGtqPZydTiQSQ= github.com/maxmind/geoipupdate/v6 v6.1.0 h1:sdtTHzzQNJlXF5+fd/EoPTucRHyMonYt/Cok8xzzfqA= @@ -197,12 +197,12 @@ github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0leargg github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/puzpuzpuz/xsync/v3 v3.5.1 h1:GJYJZwO6IdxN/IKbneznS6yPkVC+c3zyY/j19c++5Fg= github.com/puzpuzpuz/xsync/v3 v3.5.1/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA= -github.com/quic-go/quic-go v0.50.0 h1:3H/ld1pa3CYhkcc20TPIyG1bNsdhn9qZBGN3b9/UyUo= -github.com/quic-go/quic-go v0.50.0/go.mod h1:Vim6OmUvlYdwBhXP9ZVrtGmCMWa3wEqhq3NgYrI8b4E= +github.com/quic-go/quic-go v0.50.1 h1:unsgjFIUqW8a2oopkY7YNONpV1gYND6Nt9hnt1PN94Q= +github.com/quic-go/quic-go v0.50.1/go.mod h1:Vim6OmUvlYdwBhXP9ZVrtGmCMWa3wEqhq3NgYrI8b4E= github.com/rabbitmq/amqp091-go v1.10.0 h1:STpn5XsHlHGcecLmMFCtg7mqq0RnD+zFr4uzukfVhBw= github.com/rabbitmq/amqp091-go v1.10.0/go.mod h1:Hy4jKW5kQART1u+JkDTF9YYOQUHXqMuhrgxOEeS7G4o= -github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= -github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9 h1:bsUq1dX0N8AOIL7EB/X911+m4EHsnWEHeJ0c+3TTBrg= +github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/riywo/loginshell v0.0.0-20200815045211-7d26008be1ab h1:ZjX6I48eZSFetPb41dHudEyVr5v953N15TsNZXlkcWY= github.com/riywo/loginshell v0.0.0-20200815045211-7d26008be1ab/go.mod h1:/PfPXh0EntGc3QAAyUaviy4S9tzy4Zp0e2ilq4voC6E= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= @@ -211,8 +211,8 @@ github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sclevine/spec v1.4.0 h1:z/Q9idDcay5m5irkZ28M7PtQM4aOISzOpj4bUPkDee8= github.com/sclevine/spec v1.4.0/go.mod h1:LvpgJaFyvQzRvc1kaDs0bulYwzC70PbiYjC4QnFHkOM= -github.com/shirou/gopsutil/v4 v4.25.2 h1:NMscG3l2CqtWFS86kj3vP7soOczqrQYIEhO/pMvvQkk= -github.com/shirou/gopsutil/v4 v4.25.2/go.mod h1:34gBYJzyqCDT11b6bMHP0XCvWeU3J61XRT7a2EmCRTA= +github.com/shirou/gopsutil/v4 v4.25.3 h1:SeA68lsu8gLggyMbmCn8cmp97V1TI9ld9sVzAUcKcKE= +github.com/shirou/gopsutil/v4 v4.25.3/go.mod h1:xbuxyoZj+UsgnZrENu3lQivsngRR5BdjbJwf2fv4szA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= @@ -294,8 +294,8 @@ golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= -golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= -golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= +golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -382,8 +382,8 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= -google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= From f15d50c2e85136d2068e89ac6ead0159882a59c2 Mon Sep 17 00:00:00 2001 From: Tommy van der Vorst Date: Thu, 3 Apr 2025 10:12:23 +0200 Subject: [PATCH 2/2] feat(fs, config): add support for custom filesystem type construction (#9887) For Synctrain I would like to create a virtual filesystem that exposes iOS' photo library. This can only be accessed through APIs. --- lib/config/config_test.go | 4 ++- lib/config/filesystemtype.go | 43 ++++++++------------------- lib/config/folderconfiguration.go | 2 +- lib/config/versioningconfiguration.go | 4 +-- lib/fs/basicfs.go | 8 +++++ lib/fs/fakefs.go | 8 +++++ lib/fs/filesystem.go | 33 +++++++++----------- lib/fs/types.go | 42 +++++++++++++++++--------- lib/model/model_test.go | 7 +++-- lib/scanner/walk_test.go | 2 +- lib/versioner/external.go | 2 +- lib/versioner/staggered_test.go | 6 ++-- 12 files changed, 87 insertions(+), 74 deletions(-) diff --git a/lib/config/config_test.go b/lib/config/config_test.go index 14ef53308..b4d61fab4 100644 --- a/lib/config/config_test.go +++ b/lib/config/config_test.go @@ -111,6 +111,7 @@ func TestDefaultValues(t *testing.T) { AutoNormalize: true, MinDiskFree: size, Versioning: VersioningConfiguration{ + FSType: FilesystemTypeBasic, CleanupIntervalS: 3600, Params: map[string]string{}, }, @@ -520,7 +521,8 @@ func TestIssue1750(t *testing.T) { func TestFolderPath(t *testing.T) { folder := FolderConfiguration{ - Path: "~/tmp", + FilesystemType: FilesystemTypeBasic, + Path: "~/tmp", } realPath := folder.Filesystem(nil).URI() diff --git a/lib/config/filesystemtype.go b/lib/config/filesystemtype.go index eacfce6af..9608647f5 100644 --- a/lib/config/filesystemtype.go +++ b/lib/config/filesystemtype.go @@ -8,47 +8,30 @@ package config import "github.com/syncthing/syncthing/lib/fs" -type FilesystemType int32 +type FilesystemType string const ( - FilesystemTypeBasic FilesystemType = 0 - FilesystemTypeFake FilesystemType = 1 + FilesystemTypeBasic FilesystemType = "basic" + FilesystemTypeFake FilesystemType = "fake" ) -func (t FilesystemType) String() string { - switch t { - case FilesystemTypeBasic: - return "basic" - case FilesystemTypeFake: - return "fake" - default: - return "unknown" - } +func (t FilesystemType) ToFS() fs.FilesystemType { + return fs.FilesystemType(string(t)) } -func (t FilesystemType) ToFS() fs.FilesystemType { - switch t { - case FilesystemTypeBasic: - return fs.FilesystemTypeBasic - case FilesystemTypeFake: - return fs.FilesystemTypeFake - default: - return fs.FilesystemTypeBasic - } +func (t FilesystemType) String() string { + return string(t) } func (t FilesystemType) MarshalText() ([]byte, error) { - return []byte(t.String()), nil + return []byte(t), nil } func (t *FilesystemType) UnmarshalText(bs []byte) error { - switch string(bs) { - case "basic": - *t = FilesystemTypeBasic - case "fake": - *t = FilesystemTypeFake - default: - *t = FilesystemTypeBasic - } + *t = FilesystemType(string(bs)) return nil } + +func (t *FilesystemType) ParseDefault(str string) error { + return t.UnmarshalText([]byte(str)) +} diff --git a/lib/config/folderconfiguration.go b/lib/config/folderconfiguration.go index d8ec913e8..786be1f8d 100644 --- a/lib/config/folderconfiguration.go +++ b/lib/config/folderconfiguration.go @@ -47,7 +47,7 @@ type FolderDeviceConfiguration struct { type FolderConfiguration struct { ID string `json:"id" xml:"id,attr" nodefault:"true"` Label string `json:"label" xml:"label,attr" restart:"false"` - FilesystemType FilesystemType `json:"filesystemType" xml:"filesystemType"` + FilesystemType FilesystemType `json:"filesystemType" xml:"filesystemType" default:"basic"` Path string `json:"path" xml:"path,attr" default:"~"` Type FolderType `json:"type" xml:"type,attr"` Devices []FolderDeviceConfiguration `json:"devices" xml:"device"` diff --git a/lib/config/versioningconfiguration.go b/lib/config/versioningconfiguration.go index 1aa4cb06e..988f8ab44 100644 --- a/lib/config/versioningconfiguration.go +++ b/lib/config/versioningconfiguration.go @@ -20,7 +20,7 @@ type VersioningConfiguration struct { Params map[string]string `json:"params" xml:"parameter" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` CleanupIntervalS int `json:"cleanupIntervalS" xml:"cleanupIntervalS" default:"3600"` FSPath string `json:"fsPath" xml:"fsPath"` - FSType FilesystemType `json:"fsType" xml:"fsType"` + FSType FilesystemType `json:"fsType" xml:"fsType" default:"basic"` } func (c *VersioningConfiguration) Reset() { @@ -33,7 +33,7 @@ type internalVersioningConfiguration struct { Params []internalParam `xml:"param"` CleanupIntervalS int `xml:"cleanupIntervalS" default:"3600"` FSPath string `xml:"fsPath"` - FSType FilesystemType `xml:"fsType"` + FSType FilesystemType `xml:"fsType" default:"basic"` } type internalParam struct { diff --git a/lib/fs/basicfs.go b/lib/fs/basicfs.go index 6a5d58c74..225eb8132 100644 --- a/lib/fs/basicfs.go +++ b/lib/fs/basicfs.go @@ -19,6 +19,8 @@ import ( "github.com/syncthing/syncthing/lib/build" ) +const FilesystemTypeBasic FilesystemType = "basic" + var ( errInvalidFilenameEmpty = errors.New("name is invalid, must not be empty") errInvalidFilenameWindowsSpacePeriod = errors.New("name is invalid, must not end in space or period on Windows") @@ -56,6 +58,12 @@ type ( groupCache = valueCache[string, *user.Group] ) +func init() { + RegisterFilesystemType(FilesystemTypeBasic, func(root string, opts ...Option) (Filesystem, error) { + return newBasicFilesystem(root, opts...), nil + }) +} + func newBasicFilesystem(root string, opts ...Option) *BasicFilesystem { if root == "" { root = "." // Otherwise "" becomes "/" below diff --git a/lib/fs/fakefs.go b/lib/fs/fakefs.go index 5c693afa6..9429350eb 100644 --- a/lib/fs/fakefs.go +++ b/lib/fs/fakefs.go @@ -26,6 +26,14 @@ import ( "github.com/syncthing/syncthing/lib/protocol" ) +const FilesystemTypeFake FilesystemType = "fake" + +func init() { + RegisterFilesystemType(FilesystemTypeFake, func(root string, opts ...Option) (Filesystem, error) { + return newFakeFilesystem(root, opts...), nil + }) +} + // see readShortAt() const randomBlockShift = 14 // 128k diff --git a/lib/fs/filesystem.go b/lib/fs/filesystem.go index a727e2239..2d7ffbadd 100644 --- a/lib/fs/filesystem.go +++ b/lib/fs/filesystem.go @@ -9,6 +9,7 @@ package fs import ( "context" "errors" + "fmt" "io" "io/fs" "os" @@ -215,17 +216,6 @@ func IsPermission(err error) bool { // IsPathSeparator is the equivalent of os.IsPathSeparator var IsPathSeparator = os.IsPathSeparator -// Option modifies a filesystem at creation. An option might be specific -// to a filesystem-type. -// -// String is used to detect options with the same effect, i.e. must be different -// for options with different effects. Meaning if an option has parameters, a -// representation of those must be part of the returned string. -type Option interface { - String() string - apply(Filesystem) Filesystem -} - func NewFilesystem(fsType FilesystemType, uri string, opts ...Option) Filesystem { var caseOpt Option var mtimeOpt Option @@ -246,18 +236,23 @@ func NewFilesystem(fsType FilesystemType, uri string, opts ...Option) Filesystem } opts = opts[:i] + // Construct file system using the registered factory function var fs Filesystem - switch fsType { - case FilesystemTypeBasic: - fs = newBasicFilesystem(uri, opts...) - case FilesystemTypeFake: - fs = newFakeFilesystem(uri, opts...) - default: - l.Debugln("Unknown filesystem", fsType, uri) + var err error + filesystemFactoriesMutex.Lock() + fsFactory, factoryFound := filesystemFactories[fsType] + filesystemFactoriesMutex.Unlock() + if factoryFound { + fs, err = fsFactory(uri, opts...) + } else { + err = fmt.Errorf("File system type '%s' not recognized", fsType) + } + + if err != nil { fs = &errorFilesystem{ fsType: fsType, uri: uri, - err: errors.New("filesystem with type " + fsType.String() + " does not exist."), + err: err, } } diff --git a/lib/fs/types.go b/lib/fs/types.go index 243ea60c8..7dc86c9fb 100644 --- a/lib/fs/types.go +++ b/lib/fs/types.go @@ -6,20 +6,34 @@ package fs -type FilesystemType int32 +import "sync" -const ( - FilesystemTypeBasic FilesystemType = 0 - FilesystemTypeFake FilesystemType = 1 -) +type FilesystemType string -func (t FilesystemType) String() string { - switch t { - case FilesystemTypeBasic: - return "basic" - case FilesystemTypeFake: - return "fake" - default: - return "unknown" - } +// Option modifies a filesystem at creation. An option might be specific +// to a filesystem-type. +// +// String is used to detect options with the same effect, i.e. must be different +// for options with different effects. Meaning if an option has parameters, a +// representation of those must be part of the returned string. +type Option interface { + String() string + apply(Filesystem) Filesystem +} + +// Factory function type for constructing a custom file system. It takes the URI +// and options as its parameters. +type FilesystemFactory func(string, ...Option) (Filesystem, error) + +// For each registered file system type, a function to construct a file system. +var filesystemFactories map[FilesystemType]FilesystemFactory = make(map[FilesystemType]FilesystemFactory) +var filesystemFactoriesMutex sync.Mutex = sync.Mutex{} + +// Register a function to be called when a filesystem is to be constructed with +// the specified fsType. The function will receive the URI for the file system as well +// as all options. +func RegisterFilesystemType(fsType FilesystemType, fn FilesystemFactory) { + filesystemFactoriesMutex.Lock() + defer filesystemFactoriesMutex.Unlock() + filesystemFactories[fsType] = fn } diff --git a/lib/model/model_test.go b/lib/model/model_test.go index 1c79f0e1e..ebffee28d 100644 --- a/lib/model/model_test.go +++ b/lib/model/model_test.go @@ -2774,9 +2774,10 @@ func TestIssue4903(t *testing.T) { folderPath := "nonexistent" cfg := defaultCfgWrapper.RawCopy() fcfg := config.FolderConfiguration{ - ID: "folder1", - Path: folderPath, - Paused: true, + ID: "folder1", + Path: folderPath, + FilesystemType: config.FilesystemTypeBasic, + Paused: true, Devices: []config.FolderDeviceConfiguration{ {DeviceID: device1}, }, diff --git a/lib/scanner/walk_test.go b/lib/scanner/walk_test.go index 5c6254d29..266399244 100644 --- a/lib/scanner/walk_test.go +++ b/lib/scanner/walk_test.go @@ -677,7 +677,7 @@ func TestStopWalk(t *testing.T) { // Use an errorFs as the backing fs for the rest of the interface // The way we get it is a bit hacky tho. - errorFs := fs.NewFilesystem(fs.FilesystemType(-1), ".") + errorFs := fs.NewFilesystem(fs.FilesystemType("error"), ".") fs := fs.NewWalkFilesystem(&infiniteFS{errorFs, 100, 100, 1e6}) const numHashers = 4 diff --git a/lib/versioner/external.go b/lib/versioner/external.go index 2a5559408..656bdfa72 100644 --- a/lib/versioner/external.go +++ b/lib/versioner/external.go @@ -74,7 +74,7 @@ func (v external) Archive(filePath string) error { } context := map[string]string{ - "%FOLDER_FILESYSTEM%": v.filesystem.Type().String(), + "%FOLDER_FILESYSTEM%": string(v.filesystem.Type()), "%FOLDER_PATH%": v.filesystem.URI(), "%FILE_PATH%": filePath, } diff --git a/lib/versioner/staggered_test.go b/lib/versioner/staggered_test.go index 60b8065b1..534705599 100644 --- a/lib/versioner/staggered_test.go +++ b/lib/versioner/staggered_test.go @@ -139,10 +139,12 @@ func TestCreateVersionPath(t *testing.T) { } folderCfg := config.FolderConfiguration{ - ID: "default", - Path: tmpDir, + ID: "default", + FilesystemType: config.FilesystemTypeBasic, + Path: tmpDir, Versioning: config.VersioningConfiguration{ Type: "staggered", + FSType: config.FilesystemTypeBasic, FSPath: versionsDir, }, }