refactor: use modern Protobuf encoder (#9817)
At a high level, this is what I've done and why:
- I'm moving the protobuf generation for the `protocol`, `discovery` and
`db` packages to the modern alternatives, and using `buf` to generate
because it's nice and simple.
- After trying various approaches on how to integrate the new types with
the existing code, I opted for splitting off our own data model types
from the on-the-wire generated types. This means we can have a
`FileInfo` type with nicer ergonomics and lots of methods, while the
protobuf generated type stays clean and close to the wire protocol. It
does mean copying between the two when required, which certainly adds a
small amount of inefficiency. If we want to walk this back in the future
and use the raw generated type throughout, that's possible, this however
makes the refactor smaller (!) as it doesn't change everything about the
type for everyone at the same time.
- I have simply removed in cold blood a significant number of old
database migrations. These depended on previous generations of generated
messages of various kinds and were annoying to support in the new
fashion. The oldest supported database version now is the one from
Syncthing 1.9.0 from Sep 7, 2020.
- I changed config structs to be regular manually defined structs.
For the sake of discussion, some things I tried that turned out not to
work...
### Embedding / wrapping
Embedding the protobuf generated structs in our existing types as a data
container and keeping our methods and stuff:
```
package protocol
type FileInfo struct {
*generated.FileInfo
}
```
This generates a lot of problems because the internal shape of the
generated struct is quite different (different names, different types,
more pointers), because initializing it doesn't work like you'd expect
(i.e., you end up with an embedded nil pointer and a panic), and because
the types of child types don't get wrapped. That is, even if we also
have a similar wrapper around a `Vector`, that's not the type you get
when accessing `someFileInfo.Version`, you get the `*generated.Vector`
that doesn't have methods, etc.
### Aliasing
```
package protocol
type FileInfo = generated.FileInfo
```
Doesn't help because you can't attach methods to it, plus all the above.
### Generating the types into the target package like we do now and
attaching methods
This fails because of the different shape of the generated type (as in
the embedding case above) plus the generated struct already has a bunch
of methods that we can't necessarily override properly (like `String()`
and a bunch of getters).
### Methods to functions
I considered just moving all the methods we attach to functions in a
specific package, so that for example
```
package protocol
func (f FileInfo) Equal(other FileInfo) bool
```
would become
```
package fileinfos
func Equal(a, b *generated.FileInfo) bool
```
and this would mostly work, but becomes quite verbose and cumbersome,
and somewhat limits discoverability (you can't see what methods are
available on the type in auto completions, etc). In the end I did this
in some cases, like in the database layer where a lot of things like
`func (fv *FileVersion) IsEmpty() bool` becomes `func fvIsEmpty(fv
*generated.FileVersion)` because they were anyway just internal methods.
Fixes #8247
This commit is contained in:
+6
-14
@@ -1748,10 +1748,10 @@ func (*service) getSystemBrowse(w http.ResponseWriter, r *http.Request) {
|
||||
current := qs.Get("current")
|
||||
|
||||
// Default value or in case of error unmarshalling ends up being basic fs.
|
||||
var fsType fs.FilesystemType
|
||||
var fsType config.FilesystemType
|
||||
fsType.UnmarshalText([]byte(qs.Get("filesystem")))
|
||||
|
||||
sendJSON(w, browse(fsType, current))
|
||||
sendJSON(w, browse(fsType.ToFS(), current))
|
||||
}
|
||||
|
||||
func browse(fsType fs.FilesystemType, current string) []string {
|
||||
@@ -1870,10 +1870,10 @@ func (*service) getHeapProf(w http.ResponseWriter, _ *http.Request) {
|
||||
pprof.WriteHeapProfile(w)
|
||||
}
|
||||
|
||||
func toJsonFileInfoSlice(fs []db.FileInfoTruncated) []jsonFileInfoTrunc {
|
||||
res := make([]jsonFileInfoTrunc, len(fs))
|
||||
func toJsonFileInfoSlice(fs []protocol.FileInfo) []jsonFileInfo {
|
||||
res := make([]jsonFileInfo, len(fs))
|
||||
for i, f := range fs {
|
||||
res[i] = jsonFileInfoTrunc(f)
|
||||
res[i] = jsonFileInfo(f)
|
||||
}
|
||||
return res
|
||||
}
|
||||
@@ -1888,15 +1888,7 @@ func (f jsonFileInfo) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(m)
|
||||
}
|
||||
|
||||
type jsonFileInfoTrunc db.FileInfoTruncated
|
||||
|
||||
func (f jsonFileInfoTrunc) MarshalJSON() ([]byte, error) {
|
||||
m := fileIntfJSONMap(db.FileInfoTruncated(f))
|
||||
m["numBlocks"] = nil // explicitly unknown
|
||||
return json.Marshal(m)
|
||||
}
|
||||
|
||||
func fileIntfJSONMap(f protocol.FileIntf) map[string]interface{} {
|
||||
func fileIntfJSONMap(f protocol.FileInfo) map[string]interface{} {
|
||||
out := map[string]interface{}{
|
||||
"name": f.FileName(),
|
||||
"type": f.FileType().String(),
|
||||
|
||||
+2
-1
@@ -25,6 +25,8 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/d4l3k/messagediff"
|
||||
"github.com/thejerf/suture/v4"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/assets"
|
||||
"github.com/syncthing/syncthing/lib/build"
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
@@ -46,7 +48,6 @@ import (
|
||||
"github.com/syncthing/syncthing/lib/sync"
|
||||
"github.com/syncthing/syncthing/lib/tlsutil"
|
||||
"github.com/syncthing/syncthing/lib/ur"
|
||||
"github.com/thejerf/suture/v4"
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
@@ -12,6 +12,9 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
"github.com/syncthing/syncthing/internal/gen/apiproto"
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/db"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
@@ -28,16 +31,16 @@ type tokenManager struct {
|
||||
timeNow func() time.Time // can be overridden for testing
|
||||
|
||||
mut sync.Mutex
|
||||
tokens *TokenSet
|
||||
tokens *apiproto.TokenSet
|
||||
saveTimer *time.Timer
|
||||
}
|
||||
|
||||
func newTokenManager(key string, miscDB *db.NamespacedKV, lifetime time.Duration, maxItems int) *tokenManager {
|
||||
tokens := &TokenSet{
|
||||
tokens := &apiproto.TokenSet{
|
||||
Tokens: make(map[string]int64),
|
||||
}
|
||||
if bs, ok, _ := miscDB.Bytes(key); ok {
|
||||
_ = tokens.Unmarshal(bs) // best effort
|
||||
_ = proto.Unmarshal(bs, tokens) // best effort
|
||||
}
|
||||
return &tokenManager{
|
||||
key: key,
|
||||
@@ -136,7 +139,7 @@ func (m *tokenManager) scheduledSave() {
|
||||
|
||||
m.saveTimer = nil
|
||||
|
||||
bs, _ := m.tokens.Marshal() // can't fail
|
||||
bs, _ := proto.Marshal(m.tokens) // can't fail
|
||||
_ = m.miscDB.PutBytes(m.key, bs) // can fail, but what are we going to do?
|
||||
}
|
||||
|
||||
|
||||
@@ -1,411 +0,0 @@
|
||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: lib/api/tokenset.proto
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
io "io"
|
||||
math "math"
|
||||
math_bits "math/bits"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
type TokenSet struct {
|
||||
// token -> expiry time (epoch nanoseconds)
|
||||
Tokens map[string]int64 `protobuf:"bytes,1,rep,name=tokens,proto3" json:"tokens" xml:"token" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
|
||||
}
|
||||
|
||||
func (m *TokenSet) Reset() { *m = TokenSet{} }
|
||||
func (m *TokenSet) String() string { return proto.CompactTextString(m) }
|
||||
func (*TokenSet) ProtoMessage() {}
|
||||
func (*TokenSet) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_9ea8707737c33b38, []int{0}
|
||||
}
|
||||
func (m *TokenSet) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *TokenSet) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_TokenSet.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *TokenSet) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_TokenSet.Merge(m, src)
|
||||
}
|
||||
func (m *TokenSet) XXX_Size() int {
|
||||
return m.ProtoSize()
|
||||
}
|
||||
func (m *TokenSet) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_TokenSet.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_TokenSet proto.InternalMessageInfo
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*TokenSet)(nil), "api.TokenSet")
|
||||
proto.RegisterMapType((map[string]int64)(nil), "api.TokenSet.TokensEntry")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("lib/api/tokenset.proto", fileDescriptor_9ea8707737c33b38) }
|
||||
|
||||
var fileDescriptor_9ea8707737c33b38 = []byte{
|
||||
// 260 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xcb, 0xc9, 0x4c, 0xd2,
|
||||
0x4f, 0x2c, 0xc8, 0xd4, 0x2f, 0xc9, 0xcf, 0x4e, 0xcd, 0x2b, 0x4e, 0x2d, 0xd1, 0x2b, 0x28, 0xca,
|
||||
0x2f, 0xc9, 0x17, 0x62, 0x4e, 0x2c, 0xc8, 0x54, 0x3a, 0xce, 0xc8, 0xc5, 0x11, 0x02, 0x12, 0x0f,
|
||||
0x4e, 0x2d, 0x11, 0x0a, 0xe0, 0x62, 0x83, 0xa8, 0x91, 0x60, 0x54, 0x60, 0xd6, 0xe0, 0x36, 0x92,
|
||||
0xd4, 0x4b, 0x2c, 0xc8, 0xd4, 0x83, 0x49, 0x43, 0x18, 0xc5, 0xae, 0x79, 0x25, 0x45, 0x95, 0x4e,
|
||||
0xb2, 0x27, 0xee, 0xc9, 0x33, 0xbc, 0xba, 0x27, 0x0f, 0xd5, 0xf0, 0xe9, 0x9e, 0x3c, 0x77, 0x45,
|
||||
0x6e, 0x8e, 0x95, 0x12, 0x98, 0xab, 0x14, 0x04, 0x15, 0x96, 0xca, 0xe4, 0xe2, 0x46, 0xd2, 0x25,
|
||||
0xa4, 0xc6, 0xc5, 0x9c, 0x9d, 0x5a, 0x29, 0xc1, 0xa8, 0xc0, 0xa8, 0xc1, 0xe9, 0x24, 0xf2, 0xea,
|
||||
0x9e, 0x3c, 0x88, 0xfb, 0xe9, 0x9e, 0x3c, 0x27, 0x58, 0x6f, 0x76, 0x6a, 0xa5, 0x52, 0x10, 0x48,
|
||||
0x44, 0x48, 0x8f, 0x8b, 0xb5, 0x2c, 0x31, 0xa7, 0x34, 0x55, 0x82, 0x49, 0x81, 0x51, 0x83, 0xd9,
|
||||
0x49, 0xe2, 0xd5, 0x3d, 0x79, 0x88, 0x00, 0xdc, 0x1e, 0x30, 0x4f, 0x29, 0x08, 0x22, 0x6a, 0xc5,
|
||||
0x64, 0xc1, 0xe8, 0xe4, 0x71, 0xe2, 0xa1, 0x1c, 0xc3, 0x85, 0x87, 0x72, 0x0c, 0x27, 0x1e, 0xc9,
|
||||
0x31, 0x5e, 0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1, 0x1c, 0xc3, 0x82, 0xc7, 0x72, 0x8c, 0x17, 0x1e,
|
||||
0xcb, 0x31, 0xdc, 0x78, 0x2c, 0xc7, 0x10, 0xa5, 0x96, 0x9e, 0x59, 0x92, 0x51, 0x9a, 0xa4, 0x97,
|
||||
0x9c, 0x9f, 0xab, 0x5f, 0x5c, 0x99, 0x97, 0x5c, 0x92, 0x91, 0x99, 0x97, 0x8e, 0xc4, 0x82, 0x86,
|
||||
0x53, 0x12, 0x1b, 0x38, 0x7c, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0xfe, 0x25, 0x31, 0x49,
|
||||
0x39, 0x01, 0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *TokenSet) Marshal() (dAtA []byte, err error) {
|
||||
size := m.ProtoSize()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *TokenSet) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.ProtoSize()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *TokenSet) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Tokens) > 0 {
|
||||
for k := range m.Tokens {
|
||||
v := m.Tokens[k]
|
||||
baseI := i
|
||||
i = encodeVarintTokenset(dAtA, i, uint64(v))
|
||||
i--
|
||||
dAtA[i] = 0x10
|
||||
i -= len(k)
|
||||
copy(dAtA[i:], k)
|
||||
i = encodeVarintTokenset(dAtA, i, uint64(len(k)))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
i = encodeVarintTokenset(dAtA, i, uint64(baseI-i))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func encodeVarintTokenset(dAtA []byte, offset int, v uint64) int {
|
||||
offset -= sovTokenset(v)
|
||||
base := offset
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return base
|
||||
}
|
||||
func (m *TokenSet) ProtoSize() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Tokens) > 0 {
|
||||
for k, v := range m.Tokens {
|
||||
_ = k
|
||||
_ = v
|
||||
mapEntrySize := 1 + len(k) + sovTokenset(uint64(len(k))) + 1 + sovTokenset(uint64(v))
|
||||
n += mapEntrySize + 1 + sovTokenset(uint64(mapEntrySize))
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovTokenset(x uint64) (n int) {
|
||||
return (math_bits.Len64(x|1) + 6) / 7
|
||||
}
|
||||
func sozTokenset(x uint64) (n int) {
|
||||
return sovTokenset(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (m *TokenSet) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowTokenset
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: TokenSet: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: TokenSet: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Tokens", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowTokenset
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthTokenset
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthTokenset
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if m.Tokens == nil {
|
||||
m.Tokens = make(map[string]int64)
|
||||
}
|
||||
var mapkey string
|
||||
var mapvalue int64
|
||||
for iNdEx < postIndex {
|
||||
entryPreIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowTokenset
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
if fieldNum == 1 {
|
||||
var stringLenmapkey uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowTokenset
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLenmapkey |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLenmapkey := int(stringLenmapkey)
|
||||
if intStringLenmapkey < 0 {
|
||||
return ErrInvalidLengthTokenset
|
||||
}
|
||||
postStringIndexmapkey := iNdEx + intStringLenmapkey
|
||||
if postStringIndexmapkey < 0 {
|
||||
return ErrInvalidLengthTokenset
|
||||
}
|
||||
if postStringIndexmapkey > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
mapkey = string(dAtA[iNdEx:postStringIndexmapkey])
|
||||
iNdEx = postStringIndexmapkey
|
||||
} else if fieldNum == 2 {
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowTokenset
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
mapvalue |= int64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
iNdEx = entryPreIndex
|
||||
skippy, err := skipTokenset(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthTokenset
|
||||
}
|
||||
if (iNdEx + skippy) > postIndex {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
m.Tokens[mapkey] = mapvalue
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipTokenset(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthTokenset
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipTokenset(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
depth := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowTokenset
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowTokenset
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if dAtA[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowTokenset
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthTokenset
|
||||
}
|
||||
iNdEx += length
|
||||
case 3:
|
||||
depth++
|
||||
case 4:
|
||||
if depth == 0 {
|
||||
return 0, ErrUnexpectedEndOfGroupTokenset
|
||||
}
|
||||
depth--
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
if iNdEx < 0 {
|
||||
return 0, ErrInvalidLengthTokenset
|
||||
}
|
||||
if depth == 0 {
|
||||
return iNdEx, nil
|
||||
}
|
||||
}
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthTokenset = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowTokenset = fmt.Errorf("proto: integer overflow")
|
||||
ErrUnexpectedEndOfGroupTokenset = fmt.Errorf("proto: unexpected end of group")
|
||||
)
|
||||
@@ -6,6 +6,13 @@
|
||||
|
||||
package config
|
||||
|
||||
type AuthMode int32
|
||||
|
||||
const (
|
||||
AuthModeStatic AuthMode = 0
|
||||
AuthModeLDAP AuthMode = 1
|
||||
)
|
||||
|
||||
func (t AuthMode) String() string {
|
||||
switch t {
|
||||
case AuthModeStatic:
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: lib/config/authmode.proto
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
_ "github.com/gogo/protobuf/gogoproto"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
_ "github.com/syncthing/syncthing/proto/ext"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
type AuthMode int32
|
||||
|
||||
const (
|
||||
AuthModeStatic AuthMode = 0
|
||||
AuthModeLDAP AuthMode = 1
|
||||
)
|
||||
|
||||
var AuthMode_name = map[int32]string{
|
||||
0: "AUTH_MODE_STATIC",
|
||||
1: "AUTH_MODE_LDAP",
|
||||
}
|
||||
|
||||
var AuthMode_value = map[string]int32{
|
||||
"AUTH_MODE_STATIC": 0,
|
||||
"AUTH_MODE_LDAP": 1,
|
||||
}
|
||||
|
||||
func (AuthMode) EnumDescriptor() ([]byte, []int) {
|
||||
return fileDescriptor_8e30b562e1bcea1e, []int{0}
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterEnum("config.AuthMode", AuthMode_name, AuthMode_value)
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("lib/config/authmode.proto", fileDescriptor_8e30b562e1bcea1e) }
|
||||
|
||||
var fileDescriptor_8e30b562e1bcea1e = []byte{
|
||||
// 234 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xcc, 0xc9, 0x4c, 0xd2,
|
||||
0x4f, 0xce, 0xcf, 0x4b, 0xcb, 0x4c, 0xd7, 0x4f, 0x2c, 0x2d, 0xc9, 0xc8, 0xcd, 0x4f, 0x49, 0xd5,
|
||||
0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x83, 0x08, 0x4b, 0x29, 0x17, 0xa5, 0x16, 0xe4, 0x17,
|
||||
0xeb, 0x83, 0x05, 0x93, 0x4a, 0xd3, 0xf4, 0xd3, 0xf3, 0xd3, 0xf3, 0xc1, 0x1c, 0x30, 0x0b, 0xa2,
|
||||
0x58, 0x8a, 0x33, 0xb5, 0xa2, 0x04, 0xc2, 0xd4, 0x2a, 0xe0, 0xe2, 0x70, 0x2c, 0x2d, 0xc9, 0xf0,
|
||||
0xcd, 0x4f, 0x49, 0x15, 0xd2, 0xe0, 0x12, 0x70, 0x0c, 0x0d, 0xf1, 0x88, 0xf7, 0xf5, 0x77, 0x71,
|
||||
0x8d, 0x0f, 0x0e, 0x71, 0x0c, 0xf1, 0x74, 0x16, 0x60, 0x90, 0x12, 0xea, 0x9a, 0xab, 0xc0, 0x07,
|
||||
0x53, 0x13, 0x5c, 0x92, 0x58, 0x92, 0x99, 0x2c, 0x64, 0xc2, 0xc5, 0x87, 0x50, 0xe9, 0xe3, 0xe2,
|
||||
0x18, 0x20, 0xc0, 0x28, 0xa5, 0xd0, 0x35, 0x57, 0x81, 0x07, 0xa6, 0x0e, 0x24, 0x76, 0xa9, 0x4f,
|
||||
0x15, 0x85, 0x2f, 0xc5, 0xb2, 0x62, 0x89, 0x1c, 0x83, 0x93, 0xf7, 0x89, 0x87, 0x72, 0x0c, 0x17,
|
||||
0x1e, 0xca, 0x31, 0x9c, 0x78, 0x24, 0xc7, 0x78, 0xe1, 0x91, 0x1c, 0xe3, 0x84, 0xc7, 0x72, 0x0c,
|
||||
0x0b, 0x1e, 0xcb, 0x31, 0x5e, 0x78, 0x2c, 0xc7, 0x70, 0xe3, 0xb1, 0x1c, 0x43, 0x94, 0x66, 0x7a,
|
||||
0x66, 0x49, 0x46, 0x69, 0x92, 0x5e, 0x72, 0x7e, 0xae, 0x7e, 0x71, 0x65, 0x5e, 0x72, 0x49, 0x46,
|
||||
0x66, 0x5e, 0x3a, 0x12, 0x0b, 0x11, 0x0a, 0x49, 0x6c, 0x60, 0x5f, 0x18, 0x03, 0x02, 0x00, 0x00,
|
||||
0xff, 0xff, 0x48, 0x80, 0x1f, 0x0c, 0x1a, 0x01, 0x00, 0x00,
|
||||
}
|
||||
@@ -6,6 +6,14 @@
|
||||
|
||||
package config
|
||||
|
||||
type BlockPullOrder int32
|
||||
|
||||
const (
|
||||
BlockPullOrderStandard BlockPullOrder = 0
|
||||
BlockPullOrderRandom BlockPullOrder = 1
|
||||
BlockPullOrderInOrder BlockPullOrder = 2
|
||||
)
|
||||
|
||||
func (o BlockPullOrder) String() string {
|
||||
switch o {
|
||||
case BlockPullOrderStandard:
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: lib/config/blockpullorder.proto
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
_ "github.com/gogo/protobuf/gogoproto"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
type BlockPullOrder int32
|
||||
|
||||
const (
|
||||
BlockPullOrderStandard BlockPullOrder = 0
|
||||
BlockPullOrderRandom BlockPullOrder = 1
|
||||
BlockPullOrderInOrder BlockPullOrder = 2
|
||||
)
|
||||
|
||||
var BlockPullOrder_name = map[int32]string{
|
||||
0: "BLOCK_PULL_ORDER_STANDARD",
|
||||
1: "BLOCK_PULL_ORDER_RANDOM",
|
||||
2: "BLOCK_PULL_ORDER_IN_ORDER",
|
||||
}
|
||||
|
||||
var BlockPullOrder_value = map[string]int32{
|
||||
"BLOCK_PULL_ORDER_STANDARD": 0,
|
||||
"BLOCK_PULL_ORDER_RANDOM": 1,
|
||||
"BLOCK_PULL_ORDER_IN_ORDER": 2,
|
||||
}
|
||||
|
||||
func (BlockPullOrder) EnumDescriptor() ([]byte, []int) {
|
||||
return fileDescriptor_3c46a5289006da6c, []int{0}
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterEnum("config.BlockPullOrder", BlockPullOrder_name, BlockPullOrder_value)
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("lib/config/blockpullorder.proto", fileDescriptor_3c46a5289006da6c) }
|
||||
|
||||
var fileDescriptor_3c46a5289006da6c = []byte{
|
||||
// 271 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xcf, 0xc9, 0x4c, 0xd2,
|
||||
0x4f, 0xce, 0xcf, 0x4b, 0xcb, 0x4c, 0xd7, 0x4f, 0xca, 0xc9, 0x4f, 0xce, 0x2e, 0x28, 0xcd, 0xc9,
|
||||
0xc9, 0x2f, 0x4a, 0x49, 0x2d, 0xd2, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x83, 0x48, 0x4a,
|
||||
0x29, 0x17, 0xa5, 0x16, 0xe4, 0x17, 0xeb, 0x83, 0x05, 0x93, 0x4a, 0xd3, 0xf4, 0xd3, 0xf3, 0xd3,
|
||||
0xf3, 0xc1, 0x1c, 0x30, 0x0b, 0xa2, 0x58, 0xeb, 0x10, 0x23, 0x17, 0x9f, 0x13, 0xc8, 0x94, 0x80,
|
||||
0xd2, 0x9c, 0x1c, 0x7f, 0x90, 0x29, 0x42, 0x96, 0x5c, 0x92, 0x4e, 0x3e, 0xfe, 0xce, 0xde, 0xf1,
|
||||
0x01, 0xa1, 0x3e, 0x3e, 0xf1, 0xfe, 0x41, 0x2e, 0xae, 0x41, 0xf1, 0xc1, 0x21, 0x8e, 0x7e, 0x2e,
|
||||
0x8e, 0x41, 0x2e, 0x02, 0x0c, 0x52, 0x52, 0x5d, 0x73, 0x15, 0xc4, 0x50, 0xb5, 0x04, 0x97, 0x24,
|
||||
0xe6, 0xa5, 0x24, 0x16, 0xa5, 0x08, 0x99, 0x72, 0x89, 0x63, 0x68, 0x0d, 0x72, 0xf4, 0x73, 0xf1,
|
||||
0xf7, 0x15, 0x60, 0x94, 0x92, 0xe8, 0x9a, 0xab, 0x20, 0x82, 0xaa, 0x31, 0x28, 0x31, 0x2f, 0x25,
|
||||
0x3f, 0x57, 0xc8, 0x02, 0x8b, 0x8d, 0x9e, 0x7e, 0x10, 0x86, 0x00, 0x93, 0x94, 0x64, 0xd7, 0x5c,
|
||||
0x05, 0x51, 0x54, 0x8d, 0x9e, 0x79, 0x60, 0x4a, 0x8a, 0x65, 0xc5, 0x12, 0x39, 0x06, 0x27, 0xef,
|
||||
0x13, 0x0f, 0xe5, 0x18, 0x2e, 0x3c, 0x94, 0x63, 0x38, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39,
|
||||
0xc6, 0x09, 0x8f, 0xe5, 0x18, 0x16, 0x3c, 0x96, 0x63, 0xbc, 0xf0, 0x58, 0x8e, 0xe1, 0xc6, 0x63,
|
||||
0x39, 0x86, 0x28, 0xcd, 0xf4, 0xcc, 0x92, 0x8c, 0xd2, 0x24, 0xbd, 0xe4, 0xfc, 0x5c, 0xfd, 0xe2,
|
||||
0xca, 0xbc, 0xe4, 0x92, 0x8c, 0xcc, 0xbc, 0x74, 0x24, 0x16, 0x22, 0x4c, 0x93, 0xd8, 0xc0, 0x01,
|
||||
0x63, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0x8c, 0x0c, 0xb7, 0x46, 0x68, 0x01, 0x00, 0x00,
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
// Copyright (C) 2015 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 config
|
||||
|
||||
import (
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
)
|
||||
|
||||
type Compression int32
|
||||
|
||||
const (
|
||||
CompressionMetadata Compression = 0
|
||||
CompressionNever Compression = 1
|
||||
CompressionAlways Compression = 2
|
||||
)
|
||||
|
||||
var compressionMarshal = map[Compression]string{
|
||||
CompressionNever: "never",
|
||||
CompressionMetadata: "metadata",
|
||||
CompressionAlways: "always",
|
||||
}
|
||||
|
||||
var compressionUnmarshal = map[string]Compression{
|
||||
// Legacy
|
||||
"false": CompressionNever,
|
||||
"true": CompressionMetadata,
|
||||
|
||||
// Current
|
||||
"never": CompressionNever,
|
||||
"metadata": CompressionMetadata,
|
||||
"always": CompressionAlways,
|
||||
}
|
||||
|
||||
func (c Compression) MarshalText() ([]byte, error) {
|
||||
return []byte(compressionMarshal[c]), nil
|
||||
}
|
||||
|
||||
func (c *Compression) UnmarshalText(bs []byte) error {
|
||||
*c = compressionUnmarshal[string(bs)]
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c Compression) ToProtocol() protocol.Compression {
|
||||
switch c {
|
||||
case CompressionNever:
|
||||
return protocol.CompressionNever
|
||||
case CompressionAlways:
|
||||
return protocol.CompressionAlways
|
||||
case CompressionMetadata:
|
||||
return protocol.CompressionMetadata
|
||||
default:
|
||||
return protocol.CompressionMetadata
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
// Copyright (C) 2015 The Protocol Authors.
|
||||
|
||||
package protocol
|
||||
package config
|
||||
|
||||
import "testing"
|
||||
|
||||
@@ -99,6 +99,28 @@ var (
|
||||
errFolderPathEmpty = errors.New("folder has empty path")
|
||||
)
|
||||
|
||||
type Configuration struct {
|
||||
Version int `json:"version" xml:"version,attr"`
|
||||
Folders []FolderConfiguration `json:"folders" xml:"folder"`
|
||||
Devices []DeviceConfiguration `json:"devices" xml:"device"`
|
||||
GUI GUIConfiguration `json:"gui" xml:"gui"`
|
||||
LDAP LDAPConfiguration `json:"ldap" xml:"ldap"`
|
||||
Options OptionsConfiguration `json:"options" xml:"options"`
|
||||
IgnoredDevices []ObservedDevice `json:"remoteIgnoredDevices" xml:"remoteIgnoredDevice"`
|
||||
DeprecatedPendingDevices []ObservedDevice `json:"-" xml:"pendingDevice,omitempty"` // Deprecated: Do not use.
|
||||
Defaults Defaults `json:"defaults" xml:"defaults"`
|
||||
}
|
||||
|
||||
type Defaults struct {
|
||||
Folder FolderConfiguration `json:"folder" xml:"folder"`
|
||||
Device DeviceConfiguration `json:"device" xml:"device"`
|
||||
Ignores Ignores `json:"ignores" xml:"ignores"`
|
||||
}
|
||||
|
||||
type Ignores struct {
|
||||
Lines []string `json:"lines" xml:"line"`
|
||||
}
|
||||
|
||||
func New(myID protocol.DeviceID) Configuration {
|
||||
var cfg Configuration
|
||||
cfg.Version = CurrentVersion
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+13
-13
@@ -100,7 +100,7 @@ func TestDefaultValues(t *testing.T) {
|
||||
},
|
||||
Defaults: Defaults{
|
||||
Folder: FolderConfiguration{
|
||||
FilesystemType: fs.FilesystemTypeBasic,
|
||||
FilesystemType: FilesystemTypeBasic,
|
||||
Path: "~",
|
||||
Type: FolderTypeSendReceive,
|
||||
Devices: []FolderDeviceConfiguration{{DeviceID: device1}},
|
||||
@@ -127,7 +127,7 @@ func TestDefaultValues(t *testing.T) {
|
||||
Device: DeviceConfiguration{
|
||||
Addresses: []string{"dynamic"},
|
||||
AllowedNetworks: []string{},
|
||||
Compression: protocol.CompressionMetadata,
|
||||
Compression: CompressionMetadata,
|
||||
IgnoredFolders: []ObservedFolder{},
|
||||
},
|
||||
Ignores: Ignores{
|
||||
@@ -175,7 +175,7 @@ func TestDeviceConfig(t *testing.T) {
|
||||
expectedFolders := []FolderConfiguration{
|
||||
{
|
||||
ID: "test",
|
||||
FilesystemType: fs.FilesystemTypeBasic,
|
||||
FilesystemType: FilesystemTypeBasic,
|
||||
Path: "testdata",
|
||||
Devices: []FolderDeviceConfiguration{{DeviceID: device1}, {DeviceID: device4}},
|
||||
Type: FolderTypeSendOnly,
|
||||
@@ -205,7 +205,7 @@ func TestDeviceConfig(t *testing.T) {
|
||||
DeviceID: device1,
|
||||
Name: "node one",
|
||||
Addresses: []string{"tcp://a"},
|
||||
Compression: protocol.CompressionMetadata,
|
||||
Compression: CompressionMetadata,
|
||||
AllowedNetworks: []string{},
|
||||
IgnoredFolders: []ObservedFolder{},
|
||||
},
|
||||
@@ -213,7 +213,7 @@ func TestDeviceConfig(t *testing.T) {
|
||||
DeviceID: device4,
|
||||
Name: "node two",
|
||||
Addresses: []string{"tcp://b"},
|
||||
Compression: protocol.CompressionMetadata,
|
||||
Compression: CompressionMetadata,
|
||||
AllowedNetworks: []string{},
|
||||
IgnoredFolders: []ObservedFolder{},
|
||||
},
|
||||
@@ -344,7 +344,7 @@ func TestDeviceAddressesDynamic(t *testing.T) {
|
||||
DeviceID: device4,
|
||||
Name: name, // Set when auto created
|
||||
Addresses: []string{"dynamic"},
|
||||
Compression: protocol.CompressionMetadata,
|
||||
Compression: CompressionMetadata,
|
||||
AllowedNetworks: []string{},
|
||||
IgnoredFolders: []ObservedFolder{},
|
||||
},
|
||||
@@ -368,21 +368,21 @@ func TestDeviceCompression(t *testing.T) {
|
||||
device1: {
|
||||
DeviceID: device1,
|
||||
Addresses: []string{"dynamic"},
|
||||
Compression: protocol.CompressionMetadata,
|
||||
Compression: CompressionMetadata,
|
||||
AllowedNetworks: []string{},
|
||||
IgnoredFolders: []ObservedFolder{},
|
||||
},
|
||||
device2: {
|
||||
DeviceID: device2,
|
||||
Addresses: []string{"dynamic"},
|
||||
Compression: protocol.CompressionMetadata,
|
||||
Compression: CompressionMetadata,
|
||||
AllowedNetworks: []string{},
|
||||
IgnoredFolders: []ObservedFolder{},
|
||||
},
|
||||
device3: {
|
||||
DeviceID: device3,
|
||||
Addresses: []string{"dynamic"},
|
||||
Compression: protocol.CompressionNever,
|
||||
Compression: CompressionNever,
|
||||
AllowedNetworks: []string{},
|
||||
IgnoredFolders: []ObservedFolder{},
|
||||
},
|
||||
@@ -390,7 +390,7 @@ func TestDeviceCompression(t *testing.T) {
|
||||
DeviceID: device4,
|
||||
Name: name, // Set when auto created
|
||||
Addresses: []string{"dynamic"},
|
||||
Compression: protocol.CompressionMetadata,
|
||||
Compression: CompressionMetadata,
|
||||
AllowedNetworks: []string{},
|
||||
IgnoredFolders: []ObservedFolder{},
|
||||
},
|
||||
@@ -433,7 +433,7 @@ func TestDeviceAddressesStatic(t *testing.T) {
|
||||
DeviceID: device4,
|
||||
Name: name, // Set when auto created
|
||||
Addresses: []string{"dynamic"},
|
||||
Compression: protocol.CompressionMetadata,
|
||||
Compression: CompressionMetadata,
|
||||
AllowedNetworks: []string{},
|
||||
IgnoredFolders: []ObservedFolder{},
|
||||
},
|
||||
@@ -556,7 +556,7 @@ func TestFolderCheckPath(t *testing.T) {
|
||||
|
||||
for _, testcase := range testcases {
|
||||
cfg := FolderConfiguration{
|
||||
FilesystemType: fs.FilesystemTypeFake,
|
||||
FilesystemType: FilesystemTypeFake,
|
||||
MarkerName: DefaultMarkerName,
|
||||
}
|
||||
|
||||
@@ -1281,7 +1281,7 @@ func adjustDeviceConfiguration(cfg *DeviceConfiguration, id protocol.DeviceID, n
|
||||
func adjustFolderConfiguration(cfg *FolderConfiguration, id, label string, fsType fs.FilesystemType, path string) {
|
||||
cfg.ID = id
|
||||
cfg.Label = label
|
||||
cfg.FilesystemType = fsType
|
||||
cfg.FilesystemType = FilesystemType(fsType)
|
||||
cfg.Path = path
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
// 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/.
|
||||
|
||||
package config
|
||||
|
||||
import "github.com/syncthing/syncthing/lib/fs"
|
||||
|
||||
type CopyRangeMethod int32
|
||||
|
||||
const (
|
||||
CopyRangeMethodStandard CopyRangeMethod = 0
|
||||
CopyRangeMethodIoctl CopyRangeMethod = 1
|
||||
CopyRangeMethodCopyFileRange CopyRangeMethod = 2
|
||||
CopyRangeMethodSendFile CopyRangeMethod = 3
|
||||
CopyRangeMethodDuplicateExtents CopyRangeMethod = 4
|
||||
CopyRangeMethodAllWithFallback CopyRangeMethod = 5
|
||||
)
|
||||
|
||||
func (o CopyRangeMethod) String() string {
|
||||
switch o {
|
||||
case CopyRangeMethodStandard:
|
||||
return "standard"
|
||||
case CopyRangeMethodIoctl:
|
||||
return "ioctl"
|
||||
case CopyRangeMethodCopyFileRange:
|
||||
return "copy_file_range"
|
||||
case CopyRangeMethodSendFile:
|
||||
return "sendfile"
|
||||
case CopyRangeMethodDuplicateExtents:
|
||||
return "duplicate_extents"
|
||||
case CopyRangeMethodAllWithFallback:
|
||||
return "all"
|
||||
default:
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
func (o CopyRangeMethod) ToFS() fs.CopyRangeMethod {
|
||||
switch o {
|
||||
case CopyRangeMethodStandard:
|
||||
return fs.CopyRangeMethodStandard
|
||||
case CopyRangeMethodIoctl:
|
||||
return fs.CopyRangeMethodIoctl
|
||||
case CopyRangeMethodCopyFileRange:
|
||||
return fs.CopyRangeMethodCopyFileRange
|
||||
case CopyRangeMethodSendFile:
|
||||
return fs.CopyRangeMethodSendFile
|
||||
case CopyRangeMethodDuplicateExtents:
|
||||
return fs.CopyRangeMethodDuplicateExtents
|
||||
case CopyRangeMethodAllWithFallback:
|
||||
return fs.CopyRangeMethodAllWithFallback
|
||||
default:
|
||||
return fs.CopyRangeMethodStandard
|
||||
}
|
||||
}
|
||||
|
||||
func (o CopyRangeMethod) MarshalText() ([]byte, error) {
|
||||
return []byte(o.String()), nil
|
||||
}
|
||||
|
||||
func (o *CopyRangeMethod) UnmarshalText(bs []byte) error {
|
||||
switch string(bs) {
|
||||
case "standard":
|
||||
*o = CopyRangeMethodStandard
|
||||
case "ioctl":
|
||||
*o = CopyRangeMethodIoctl
|
||||
case "copy_file_range":
|
||||
*o = CopyRangeMethodCopyFileRange
|
||||
case "sendfile":
|
||||
*o = CopyRangeMethodSendFile
|
||||
case "duplicate_extents":
|
||||
*o = CopyRangeMethodDuplicateExtents
|
||||
case "all":
|
||||
*o = CopyRangeMethodAllWithFallback
|
||||
default:
|
||||
*o = CopyRangeMethodStandard
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *CopyRangeMethod) ParseDefault(str string) error {
|
||||
return o.UnmarshalText([]byte(str))
|
||||
}
|
||||
@@ -9,10 +9,34 @@ package config
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
)
|
||||
|
||||
const defaultNumConnections = 1 // number of connections to use by default; may change in the future.
|
||||
|
||||
type DeviceConfiguration struct {
|
||||
DeviceID protocol.DeviceID `json:"deviceID" xml:"id,attr" nodefault:"true"`
|
||||
Name string `json:"name" xml:"name,attr,omitempty"`
|
||||
Addresses []string `json:"addresses" xml:"address,omitempty"`
|
||||
Compression Compression `json:"compression" xml:"compression,attr"`
|
||||
CertName string `json:"certName" xml:"certName,attr,omitempty"`
|
||||
Introducer bool `json:"introducer" xml:"introducer,attr"`
|
||||
SkipIntroductionRemovals bool `json:"skipIntroductionRemovals" xml:"skipIntroductionRemovals,attr"`
|
||||
IntroducedBy protocol.DeviceID `json:"introducedBy" xml:"introducedBy,attr" nodefault:"true"`
|
||||
Paused bool `json:"paused" xml:"paused"`
|
||||
AllowedNetworks []string `json:"allowedNetworks" xml:"allowedNetwork,omitempty"`
|
||||
AutoAcceptFolders bool `json:"autoAcceptFolders" xml:"autoAcceptFolders"`
|
||||
MaxSendKbps int `json:"maxSendKbps" xml:"maxSendKbps"`
|
||||
MaxRecvKbps int `json:"maxRecvKbps" xml:"maxRecvKbps"`
|
||||
IgnoredFolders []ObservedFolder `json:"ignoredFolders" xml:"ignoredFolder"`
|
||||
DeprecatedPendingFolders []ObservedFolder `json:"-" xml:"pendingFolder,omitempty"` // Deprecated: Do not use.
|
||||
MaxRequestKiB int `json:"maxRequestKiB" xml:"maxRequestKiB"`
|
||||
Untrusted bool `json:"untrusted" xml:"untrusted"`
|
||||
RemoteGUIPort int `json:"remoteGUIPort" xml:"remoteGUIPort"`
|
||||
RawNumConnections int `json:"numConnections" xml:"numConnections"`
|
||||
}
|
||||
|
||||
func (cfg DeviceConfiguration) Copy() DeviceConfiguration {
|
||||
c := cfg
|
||||
c.Addresses = make([]string, len(cfg.Addresses))
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,54 @@
|
||||
// Copyright (C) 2016 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 config
|
||||
|
||||
import "github.com/syncthing/syncthing/lib/fs"
|
||||
|
||||
type FilesystemType int32
|
||||
|
||||
const (
|
||||
FilesystemTypeBasic FilesystemType = 0
|
||||
FilesystemTypeFake FilesystemType = 1
|
||||
)
|
||||
|
||||
func (t FilesystemType) String() string {
|
||||
switch t {
|
||||
case FilesystemTypeBasic:
|
||||
return "basic"
|
||||
case FilesystemTypeFake:
|
||||
return "fake"
|
||||
default:
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
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) MarshalText() ([]byte, error) {
|
||||
return []byte(t.String()), nil
|
||||
}
|
||||
|
||||
func (t *FilesystemType) UnmarshalText(bs []byte) error {
|
||||
switch string(bs) {
|
||||
case "basic":
|
||||
*t = FilesystemTypeBasic
|
||||
case "fake":
|
||||
*t = FilesystemTypeFake
|
||||
default:
|
||||
*t = FilesystemTypeBasic
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -33,11 +33,82 @@ var (
|
||||
|
||||
const (
|
||||
DefaultMarkerName = ".stfolder"
|
||||
EncryptionTokenName = "syncthing-encryption_password_token"
|
||||
EncryptionTokenName = "syncthing-encryption_password_token" //nolint: gosec
|
||||
maxConcurrentWritesDefault = 2
|
||||
maxConcurrentWritesLimit = 64
|
||||
)
|
||||
|
||||
type FolderDeviceConfiguration struct {
|
||||
DeviceID protocol.DeviceID `json:"deviceID" xml:"id,attr"`
|
||||
IntroducedBy protocol.DeviceID `json:"introducedBy" xml:"introducedBy,attr"`
|
||||
EncryptionPassword string `json:"encryptionPassword" xml:"encryptionPassword"`
|
||||
}
|
||||
|
||||
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"`
|
||||
Path string `json:"path" xml:"path,attr" default:"~"`
|
||||
Type FolderType `json:"type" xml:"type,attr"`
|
||||
Devices []FolderDeviceConfiguration `json:"devices" xml:"device"`
|
||||
RescanIntervalS int `json:"rescanIntervalS" xml:"rescanIntervalS,attr" default:"3600"`
|
||||
FSWatcherEnabled bool `json:"fsWatcherEnabled" xml:"fsWatcherEnabled,attr" default:"true"`
|
||||
FSWatcherDelayS float64 `json:"fsWatcherDelayS" xml:"fsWatcherDelayS,attr" default:"10"`
|
||||
FSWatcherTimeoutS float64 `json:"fsWatcherTimeoutS" xml:"fsWatcherTimeoutS,attr"`
|
||||
IgnorePerms bool `json:"ignorePerms" xml:"ignorePerms,attr"`
|
||||
AutoNormalize bool `json:"autoNormalize" xml:"autoNormalize,attr" default:"true"`
|
||||
MinDiskFree Size `json:"minDiskFree" xml:"minDiskFree" default:"1 %"`
|
||||
Versioning VersioningConfiguration `json:"versioning" xml:"versioning"`
|
||||
Copiers int `json:"copiers" xml:"copiers"`
|
||||
PullerMaxPendingKiB int `json:"pullerMaxPendingKiB" xml:"pullerMaxPendingKiB"`
|
||||
Hashers int `json:"hashers" xml:"hashers"`
|
||||
Order PullOrder `json:"order" xml:"order"`
|
||||
IgnoreDelete bool `json:"ignoreDelete" xml:"ignoreDelete"`
|
||||
ScanProgressIntervalS int `json:"scanProgressIntervalS" xml:"scanProgressIntervalS"`
|
||||
PullerPauseS int `json:"pullerPauseS" xml:"pullerPauseS"`
|
||||
MaxConflicts int `json:"maxConflicts" xml:"maxConflicts" default:"10"`
|
||||
DisableSparseFiles bool `json:"disableSparseFiles" xml:"disableSparseFiles"`
|
||||
DisableTempIndexes bool `json:"disableTempIndexes" xml:"disableTempIndexes"`
|
||||
Paused bool `json:"paused" xml:"paused"`
|
||||
WeakHashThresholdPct int `json:"weakHashThresholdPct" xml:"weakHashThresholdPct"`
|
||||
MarkerName string `json:"markerName" xml:"markerName"`
|
||||
CopyOwnershipFromParent bool `json:"copyOwnershipFromParent" xml:"copyOwnershipFromParent"`
|
||||
RawModTimeWindowS int `json:"modTimeWindowS" xml:"modTimeWindowS"`
|
||||
MaxConcurrentWrites int `json:"maxConcurrentWrites" xml:"maxConcurrentWrites" default:"2"`
|
||||
DisableFsync bool `json:"disableFsync" xml:"disableFsync"`
|
||||
BlockPullOrder BlockPullOrder `json:"blockPullOrder" xml:"blockPullOrder"`
|
||||
CopyRangeMethod CopyRangeMethod `json:"copyRangeMethod" xml:"copyRangeMethod" default:"standard"`
|
||||
CaseSensitiveFS bool `json:"caseSensitiveFS" xml:"caseSensitiveFS"`
|
||||
JunctionsAsDirs bool `json:"junctionsAsDirs" xml:"junctionsAsDirs"`
|
||||
SyncOwnership bool `json:"syncOwnership" xml:"syncOwnership"`
|
||||
SendOwnership bool `json:"sendOwnership" xml:"sendOwnership"`
|
||||
SyncXattrs bool `json:"syncXattrs" xml:"syncXattrs"`
|
||||
SendXattrs bool `json:"sendXattrs" xml:"sendXattrs"`
|
||||
XattrFilter XattrFilter `json:"xattrFilter" xml:"xattrFilter"`
|
||||
// Legacy deprecated
|
||||
DeprecatedReadOnly bool `json:"-" xml:"ro,attr,omitempty"` // Deprecated: Do not use.
|
||||
DeprecatedMinDiskFreePct float64 `json:"-" xml:"minDiskFreePct,omitempty"` // Deprecated: Do not use.
|
||||
DeprecatedPullers int `json:"-" xml:"pullers,omitempty"` // Deprecated: Do not use.
|
||||
DeprecatedScanOwnership bool `json:"-" xml:"scanOwnership,omitempty"` // Deprecated: Do not use.
|
||||
}
|
||||
|
||||
// Extended attribute filter. This is a list of patterns to match (glob
|
||||
// style), each with an action (permit or deny). First match is used. If the
|
||||
// filter is empty, all strings are permitted. If the filter is non-empty,
|
||||
// the default action becomes deny. To counter this, you can use the "*"
|
||||
// pattern to match all strings at the end of the filter. There are also
|
||||
// limits on the size of accepted attributes.
|
||||
type XattrFilter struct {
|
||||
Entries []XattrFilterEntry `json:"entries" xml:"entry"`
|
||||
MaxSingleEntrySize int `json:"maxSingleEntrySize" xml:"maxSingleEntrySize" default:"1024"`
|
||||
MaxTotalSize int `json:"maxTotalSize" xml:"maxTotalSize" default:"4096"`
|
||||
}
|
||||
|
||||
type XattrFilterEntry struct {
|
||||
Match string `json:"match" xml:"match,attr"`
|
||||
Permit bool `json:"permit" xml:"permit,attr"`
|
||||
}
|
||||
|
||||
func (f FolderConfiguration) Copy() FolderConfiguration {
|
||||
c := f
|
||||
c.Devices = make([]FolderDeviceConfiguration, len(f.Devices))
|
||||
@@ -53,7 +124,7 @@ func (f FolderConfiguration) Filesystem(fset *db.FileSet) fs.Filesystem {
|
||||
// This is intentionally not a pointer method, because things like
|
||||
// cfg.Folders["default"].Filesystem(nil) should be valid.
|
||||
opts := make([]fs.Option, 0, 3)
|
||||
if f.FilesystemType == fs.FilesystemTypeBasic && f.JunctionsAsDirs {
|
||||
if f.FilesystemType == FilesystemTypeBasic && f.JunctionsAsDirs {
|
||||
opts = append(opts, new(fs.OptionJunctionsAsDirs))
|
||||
}
|
||||
if !f.CaseSensitiveFS {
|
||||
@@ -62,7 +133,7 @@ func (f FolderConfiguration) Filesystem(fset *db.FileSet) fs.Filesystem {
|
||||
if fset != nil {
|
||||
opts = append(opts, fset.MtimeOption())
|
||||
}
|
||||
return fs.NewFilesystem(f.FilesystemType, f.Path, opts...)
|
||||
return fs.NewFilesystem(f.FilesystemType.ToFS(), f.Path, opts...)
|
||||
}
|
||||
|
||||
func (f FolderConfiguration) ModTimeWindow() time.Duration {
|
||||
@@ -300,7 +371,7 @@ func (f *FolderConfiguration) CheckAvailableSpace(req uint64) error {
|
||||
fs := f.Filesystem(nil)
|
||||
usage, err := fs.Usage(".")
|
||||
if err != nil {
|
||||
return nil
|
||||
return nil //nolint: nilerr
|
||||
}
|
||||
if err := checkAvailableSpace(req, f.MinDiskFree, usage); err != nil {
|
||||
return fmt.Errorf("insufficient space in folder %v (%v): %w", f.Description(), fs.URI(), err)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,6 +6,15 @@
|
||||
|
||||
package config
|
||||
|
||||
type FolderType int32
|
||||
|
||||
const (
|
||||
FolderTypeSendReceive FolderType = 0
|
||||
FolderTypeSendOnly FolderType = 1
|
||||
FolderTypeReceiveOnly FolderType = 2
|
||||
FolderTypeReceiveEncrypted FolderType = 3
|
||||
)
|
||||
|
||||
func (t FolderType) String() string {
|
||||
switch t {
|
||||
case FolderTypeSendReceive:
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: lib/config/foldertype.proto
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
_ "github.com/gogo/protobuf/gogoproto"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
type FolderType int32
|
||||
|
||||
const (
|
||||
FolderTypeSendReceive FolderType = 0
|
||||
FolderTypeSendOnly FolderType = 1
|
||||
FolderTypeReceiveOnly FolderType = 2
|
||||
FolderTypeReceiveEncrypted FolderType = 3
|
||||
)
|
||||
|
||||
var FolderType_name = map[int32]string{
|
||||
0: "FOLDER_TYPE_SEND_RECEIVE",
|
||||
1: "FOLDER_TYPE_SEND_ONLY",
|
||||
2: "FOLDER_TYPE_RECEIVE_ONLY",
|
||||
3: "FOLDER_TYPE_RECEIVE_ENCRYPTED",
|
||||
}
|
||||
|
||||
var FolderType_value = map[string]int32{
|
||||
"FOLDER_TYPE_SEND_RECEIVE": 0,
|
||||
"FOLDER_TYPE_SEND_ONLY": 1,
|
||||
"FOLDER_TYPE_RECEIVE_ONLY": 2,
|
||||
"FOLDER_TYPE_RECEIVE_ENCRYPTED": 3,
|
||||
}
|
||||
|
||||
func (FolderType) EnumDescriptor() ([]byte, []int) {
|
||||
return fileDescriptor_ea6ddb20c0633575, []int{0}
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterEnum("config.FolderType", FolderType_name, FolderType_value)
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("lib/config/foldertype.proto", fileDescriptor_ea6ddb20c0633575) }
|
||||
|
||||
var fileDescriptor_ea6ddb20c0633575 = []byte{
|
||||
// 287 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xce, 0xc9, 0x4c, 0xd2,
|
||||
0x4f, 0xce, 0xcf, 0x4b, 0xcb, 0x4c, 0xd7, 0x4f, 0xcb, 0xcf, 0x49, 0x49, 0x2d, 0x2a, 0xa9, 0x2c,
|
||||
0x48, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x83, 0x48, 0x48, 0x29, 0x17, 0xa5, 0x16,
|
||||
0xe4, 0x17, 0xeb, 0x83, 0x05, 0x93, 0x4a, 0xd3, 0xf4, 0xd3, 0xf3, 0xd3, 0xf3, 0xc1, 0x1c, 0x30,
|
||||
0x0b, 0xa2, 0x58, 0xeb, 0x17, 0x23, 0x17, 0x97, 0x1b, 0xd8, 0x84, 0x90, 0xca, 0x82, 0x54, 0x21,
|
||||
0x73, 0x2e, 0x09, 0x37, 0x7f, 0x1f, 0x17, 0xd7, 0xa0, 0xf8, 0x90, 0xc8, 0x00, 0xd7, 0xf8, 0x60,
|
||||
0x57, 0x3f, 0x97, 0xf8, 0x20, 0x57, 0x67, 0x57, 0xcf, 0x30, 0x57, 0x01, 0x06, 0x29, 0xc9, 0xae,
|
||||
0xb9, 0x0a, 0xa2, 0x08, 0xd5, 0xc1, 0xa9, 0x79, 0x29, 0x41, 0xa9, 0xc9, 0xa9, 0x99, 0x65, 0xa9,
|
||||
0x42, 0x86, 0x5c, 0xa2, 0x18, 0x1a, 0xfd, 0xfd, 0x7c, 0x22, 0x05, 0x18, 0xa5, 0xc4, 0xba, 0xe6,
|
||||
0x2a, 0x08, 0xa1, 0xea, 0xf2, 0xcf, 0xcb, 0xa9, 0x44, 0xb7, 0x0b, 0x6a, 0x0d, 0x44, 0x17, 0x13,
|
||||
0xba, 0x5d, 0x50, 0x7b, 0xc0, 0x1a, 0x1d, 0xb9, 0x64, 0xb1, 0x69, 0x74, 0xf5, 0x73, 0x0e, 0x8a,
|
||||
0x0c, 0x08, 0x71, 0x75, 0x11, 0x60, 0x96, 0x92, 0xeb, 0x9a, 0xab, 0x20, 0x85, 0xa1, 0xdb, 0x35,
|
||||
0x2f, 0xb9, 0xa8, 0xb2, 0xa0, 0x24, 0x35, 0x45, 0x8a, 0x65, 0xc5, 0x12, 0x39, 0x06, 0x27, 0xef,
|
||||
0x13, 0x0f, 0xe5, 0x18, 0x2e, 0x3c, 0x94, 0x63, 0x38, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39,
|
||||
0xc6, 0x09, 0x8f, 0xe5, 0x18, 0x16, 0x3c, 0x96, 0x63, 0xbc, 0xf0, 0x58, 0x8e, 0xe1, 0xc6, 0x63,
|
||||
0x39, 0x86, 0x28, 0xcd, 0xf4, 0xcc, 0x92, 0x8c, 0xd2, 0x24, 0xbd, 0xe4, 0xfc, 0x5c, 0xfd, 0xe2,
|
||||
0xca, 0xbc, 0xe4, 0x92, 0x8c, 0xcc, 0xbc, 0x74, 0x24, 0x16, 0x22, 0x1e, 0x92, 0xd8, 0xc0, 0x01,
|
||||
0x6a, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0xc9, 0x87, 0xbe, 0x2d, 0x9c, 0x01, 0x00, 0x00,
|
||||
}
|
||||
@@ -18,6 +18,23 @@ import (
|
||||
"github.com/syncthing/syncthing/lib/rand"
|
||||
)
|
||||
|
||||
type GUIConfiguration struct {
|
||||
Enabled bool `json:"enabled" xml:"enabled,attr" default:"true"`
|
||||
RawAddress string `json:"address" xml:"address" default:"127.0.0.1:8384"`
|
||||
RawUnixSocketPermissions string `json:"unixSocketPermissions" xml:"unixSocketPermissions,omitempty"`
|
||||
User string `json:"user" xml:"user,omitempty"`
|
||||
Password string `json:"password" xml:"password,omitempty"`
|
||||
AuthMode AuthMode `json:"authMode" xml:"authMode,omitempty"`
|
||||
RawUseTLS bool `json:"useTLS" xml:"tls,attr"`
|
||||
APIKey string `json:"apiKey" xml:"apikey,omitempty"`
|
||||
InsecureAdminAccess bool `json:"insecureAdminAccess" xml:"insecureAdminAccess,omitempty"`
|
||||
Theme string `json:"theme" xml:"theme" default:"default"`
|
||||
Debugging bool `json:"debugging" xml:"debugging,attr"`
|
||||
InsecureSkipHostCheck bool `json:"insecureSkipHostcheck" xml:"insecureSkipHostcheck,omitempty"`
|
||||
InsecureAllowFrameLoading bool `json:"insecureAllowFrameLoading" xml:"insecureAllowFrameLoading,omitempty"`
|
||||
SendBasicAuthPrompt bool `json:"sendBasicAuthPrompt" xml:"sendBasicAuthPrompt,attr"`
|
||||
}
|
||||
|
||||
func (c GUIConfiguration) IsAuthEnabled() bool {
|
||||
// This function should match isAuthEnabled() in syncthingController.js
|
||||
return c.AuthMode == AuthModeLDAP || (len(c.User) > 0 && len(c.Password) > 0)
|
||||
|
||||
@@ -1,840 +0,0 @@
|
||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: lib/config/guiconfiguration.proto
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
_ "github.com/syncthing/syncthing/proto/ext"
|
||||
io "io"
|
||||
math "math"
|
||||
math_bits "math/bits"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
type GUIConfiguration struct {
|
||||
Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled" xml:"enabled,attr" default:"true"`
|
||||
RawAddress string `protobuf:"bytes,2,opt,name=address,proto3" json:"address" xml:"address" default:"127.0.0.1:8384"`
|
||||
RawUnixSocketPermissions string `protobuf:"bytes,3,opt,name=unix_socket_permissions,json=unixSocketPermissions,proto3" json:"unixSocketPermissions" xml:"unixSocketPermissions,omitempty"`
|
||||
User string `protobuf:"bytes,4,opt,name=user,proto3" json:"user" xml:"user,omitempty"`
|
||||
Password string `protobuf:"bytes,5,opt,name=password,proto3" json:"password" xml:"password,omitempty"`
|
||||
AuthMode AuthMode `protobuf:"varint,6,opt,name=auth_mode,json=authMode,proto3,enum=config.AuthMode" json:"authMode" xml:"authMode,omitempty"`
|
||||
RawUseTLS bool `protobuf:"varint,7,opt,name=use_tls,json=useTls,proto3" json:"useTLS" xml:"tls,attr"`
|
||||
APIKey string `protobuf:"bytes,8,opt,name=api_key,json=apiKey,proto3" json:"apiKey" xml:"apikey,omitempty"`
|
||||
InsecureAdminAccess bool `protobuf:"varint,9,opt,name=insecure_admin_access,json=insecureAdminAccess,proto3" json:"insecureAdminAccess" xml:"insecureAdminAccess,omitempty"`
|
||||
Theme string `protobuf:"bytes,10,opt,name=theme,proto3" json:"theme" xml:"theme" default:"default"`
|
||||
Debugging bool `protobuf:"varint,11,opt,name=debugging,proto3" json:"debugging" xml:"debugging,attr"`
|
||||
InsecureSkipHostCheck bool `protobuf:"varint,12,opt,name=insecure_skip_host_check,json=insecureSkipHostCheck,proto3" json:"insecureSkipHostcheck" xml:"insecureSkipHostcheck,omitempty"`
|
||||
InsecureAllowFrameLoading bool `protobuf:"varint,13,opt,name=insecure_allow_frame_loading,json=insecureAllowFrameLoading,proto3" json:"insecureAllowFrameLoading" xml:"insecureAllowFrameLoading,omitempty"`
|
||||
SendBasicAuthPrompt bool `protobuf:"varint,14,opt,name=send_basic_auth_prompt,json=sendBasicAuthPrompt,proto3" json:"sendBasicAuthPrompt" xml:"sendBasicAuthPrompt,attr"`
|
||||
}
|
||||
|
||||
func (m *GUIConfiguration) Reset() { *m = GUIConfiguration{} }
|
||||
func (m *GUIConfiguration) String() string { return proto.CompactTextString(m) }
|
||||
func (*GUIConfiguration) ProtoMessage() {}
|
||||
func (*GUIConfiguration) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_2a9586d611855d64, []int{0}
|
||||
}
|
||||
func (m *GUIConfiguration) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *GUIConfiguration) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_GUIConfiguration.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *GUIConfiguration) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_GUIConfiguration.Merge(m, src)
|
||||
}
|
||||
func (m *GUIConfiguration) XXX_Size() int {
|
||||
return m.ProtoSize()
|
||||
}
|
||||
func (m *GUIConfiguration) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_GUIConfiguration.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_GUIConfiguration proto.InternalMessageInfo
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*GUIConfiguration)(nil), "config.GUIConfiguration")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("lib/config/guiconfiguration.proto", fileDescriptor_2a9586d611855d64) }
|
||||
|
||||
var fileDescriptor_2a9586d611855d64 = []byte{
|
||||
// 888 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x55, 0xcd, 0x6e, 0xdb, 0x46,
|
||||
0x10, 0x16, 0x5b, 0x47, 0xb2, 0xb6, 0x89, 0x60, 0xb0, 0x4d, 0xca, 0x04, 0x0d, 0xd7, 0x51, 0xd8,
|
||||
0xc2, 0x01, 0x02, 0x39, 0x71, 0x5a, 0x24, 0xf0, 0xa1, 0x80, 0x1c, 0x20, 0x4d, 0x60, 0x17, 0x30,
|
||||
0xe8, 0xfa, 0x92, 0x0b, 0xb1, 0x22, 0xd7, 0xd2, 0x42, 0xfc, 0x2b, 0x77, 0x09, 0x5b, 0x87, 0xf6,
|
||||
0x01, 0x7a, 0x2a, 0xdc, 0x73, 0x81, 0x3e, 0x43, 0x2f, 0x7d, 0x85, 0xdc, 0xa4, 0x53, 0xd1, 0xd3,
|
||||
0x02, 0x91, 0xd1, 0x0b, 0x8f, 0x3c, 0xe6, 0x54, 0xec, 0xf2, 0x47, 0xa2, 0x4c, 0x37, 0xb9, 0xed,
|
||||
0x7c, 0xf3, 0xcd, 0x7c, 0x33, 0xc3, 0x19, 0x10, 0xdc, 0x73, 0xc9, 0x60, 0xdb, 0x0e, 0xfc, 0x13,
|
||||
0x32, 0xdc, 0x1e, 0xc6, 0x24, 0x7b, 0xc5, 0x11, 0x62, 0x24, 0xf0, 0x7b, 0x61, 0x14, 0xb0, 0x40,
|
||||
0x6d, 0x66, 0xe0, 0x9d, 0xdb, 0x4b, 0x54, 0x14, 0xb3, 0x91, 0x17, 0x38, 0x38, 0xa3, 0xdc, 0x69,
|
||||
0xe3, 0x33, 0x96, 0x3d, 0xbb, 0xff, 0xde, 0x00, 0x1b, 0xdf, 0x1d, 0xbf, 0x7a, 0xbe, 0x9c, 0x48,
|
||||
0x1d, 0x80, 0x16, 0xf6, 0xd1, 0xc0, 0xc5, 0x8e, 0xa6, 0x6c, 0x2a, 0x5b, 0xeb, 0x7b, 0x2f, 0x13,
|
||||
0x0e, 0x0b, 0x28, 0xe5, 0xf0, 0xde, 0x99, 0xe7, 0xee, 0x76, 0x73, 0xfb, 0x21, 0x62, 0x2c, 0xea,
|
||||
0x6e, 0x3a, 0xf8, 0x04, 0xc5, 0x2e, 0xdb, 0xed, 0xb2, 0x28, 0xc6, 0xdd, 0x64, 0x6a, 0x5c, 0x5f,
|
||||
0xf6, 0xbf, 0x9b, 0x1a, 0x6b, 0xc2, 0x61, 0x16, 0x59, 0xd4, 0x9f, 0x40, 0x0b, 0x39, 0x4e, 0x84,
|
||||
0x29, 0xd5, 0x3e, 0xda, 0x54, 0xb6, 0xda, 0x7b, 0xf6, 0x9c, 0x43, 0x60, 0xa2, 0xd3, 0x7e, 0x86,
|
||||
0x0a, 0xc5, 0x9c, 0x90, 0x72, 0xf8, 0x95, 0x54, 0xcc, 0xed, 0x25, 0xb1, 0xc7, 0x3b, 0x4f, 0x7b,
|
||||
0x8f, 0x7a, 0x8f, 0x7a, 0x8f, 0x77, 0x9f, 0x3d, 0x79, 0xf6, 0x75, 0xf7, 0xdd, 0xd4, 0xe8, 0x54,
|
||||
0xa1, 0xf3, 0x99, 0xb1, 0x94, 0xd4, 0x2c, 0x52, 0xaa, 0x7f, 0x2b, 0xe0, 0xf3, 0xd8, 0x27, 0x67,
|
||||
0x16, 0x0d, 0xec, 0x31, 0x66, 0x56, 0x88, 0x23, 0x8f, 0x50, 0x4a, 0x02, 0x9f, 0x6a, 0x1f, 0xcb,
|
||||
0x7a, 0x7e, 0x57, 0xe6, 0x1c, 0x6a, 0x26, 0x3a, 0x3d, 0xf6, 0xc9, 0xd9, 0x91, 0x64, 0x1d, 0x2e,
|
||||
0x48, 0x09, 0x87, 0x37, 0xe3, 0x3a, 0x47, 0xca, 0xe1, 0x97, 0xb2, 0xd8, 0x5a, 0xef, 0xc3, 0xc0,
|
||||
0x23, 0x0c, 0x7b, 0x21, 0x9b, 0x88, 0x11, 0xc1, 0xf7, 0x70, 0xce, 0x67, 0xc6, 0x95, 0x05, 0x98,
|
||||
0xf5, 0xf2, 0xea, 0x0b, 0xb0, 0x16, 0x53, 0x1c, 0x69, 0x6b, 0xb2, 0x89, 0x9d, 0x84, 0x43, 0x69,
|
||||
0xa7, 0x1c, 0x7e, 0x96, 0x95, 0x45, 0x71, 0x54, 0xad, 0xa2, 0x53, 0x85, 0x4c, 0xc9, 0x57, 0x5f,
|
||||
0x83, 0xf5, 0x10, 0x51, 0x7a, 0x1a, 0x44, 0x8e, 0x76, 0x4d, 0xe6, 0xfa, 0x36, 0xe1, 0xb0, 0xc4,
|
||||
0x52, 0x0e, 0x35, 0x99, 0xaf, 0x00, 0xaa, 0x39, 0xd5, 0xcb, 0xb0, 0x59, 0xc6, 0xaa, 0x1e, 0x68,
|
||||
0x8b, 0x8d, 0xb4, 0xc4, 0x4a, 0x6a, 0xcd, 0x4d, 0x65, 0xab, 0xb3, 0xb3, 0xd1, 0xcb, 0x56, 0xb5,
|
||||
0xd7, 0x8f, 0xd9, 0xe8, 0xfb, 0xc0, 0xc1, 0x99, 0x1c, 0xca, 0xad, 0x52, 0xae, 0x00, 0x56, 0xe4,
|
||||
0x2e, 0xc3, 0x66, 0x19, 0xab, 0x62, 0xd0, 0x8a, 0x29, 0xb6, 0x98, 0x4b, 0xb5, 0x96, 0x5c, 0xe7,
|
||||
0x83, 0x39, 0x87, 0x6d, 0x31, 0x58, 0x8a, 0x7f, 0x38, 0x38, 0x4a, 0x38, 0x6c, 0xc6, 0xf2, 0x95,
|
||||
0x72, 0xd8, 0x91, 0x2a, 0xcc, 0xa5, 0xd9, 0x5a, 0x27, 0x53, 0x63, 0xbd, 0x30, 0xd2, 0xa9, 0x91,
|
||||
0xf3, 0xce, 0x67, 0xc6, 0x22, 0xdc, 0x94, 0xa0, 0x4b, 0x85, 0x0c, 0x0a, 0x89, 0x35, 0xc6, 0x13,
|
||||
0x6d, 0x5d, 0x0e, 0x4c, 0xc8, 0x34, 0xfb, 0x87, 0xaf, 0xf6, 0xf1, 0x44, 0x68, 0xa0, 0x90, 0xec,
|
||||
0xe3, 0x49, 0xca, 0xe1, 0xad, 0xac, 0x93, 0x90, 0x8c, 0xf1, 0xa4, 0xda, 0xc7, 0xc6, 0x2a, 0x78,
|
||||
0x3e, 0x33, 0xf2, 0x0c, 0x66, 0x1e, 0xaf, 0xfe, 0xa6, 0x80, 0x9b, 0xc4, 0xa7, 0xd8, 0x8e, 0x23,
|
||||
0x6c, 0x21, 0xc7, 0x23, 0xbe, 0x85, 0x6c, 0x5b, 0xdc, 0x51, 0x5b, 0x36, 0x67, 0x25, 0x1c, 0x7e,
|
||||
0x5a, 0x10, 0xfa, 0xc2, 0xdf, 0x97, 0xee, 0x94, 0xc3, 0xfb, 0x52, 0xb8, 0xc6, 0x57, 0xad, 0xe2,
|
||||
0xee, 0xff, 0x32, 0xcc, 0xba, 0xe4, 0xea, 0x3e, 0xb8, 0xc6, 0x46, 0xd8, 0xc3, 0x1a, 0x90, 0xad,
|
||||
0x7f, 0x93, 0x70, 0x98, 0x01, 0x29, 0x87, 0x77, 0xb3, 0x99, 0x0a, 0x6b, 0xe9, 0x74, 0xf3, 0x87,
|
||||
0xb8, 0xd9, 0x56, 0xfe, 0x36, 0xb3, 0x10, 0xf5, 0x18, 0xb4, 0x1d, 0x3c, 0x88, 0x87, 0x43, 0xe2,
|
||||
0x0f, 0xb5, 0x4f, 0x64, 0x57, 0x4f, 0x13, 0x0e, 0x17, 0x60, 0xb9, 0xcd, 0x25, 0x52, 0x7e, 0xae,
|
||||
0x4e, 0x15, 0x32, 0x17, 0x41, 0xea, 0x5f, 0x0a, 0xd0, 0xca, 0xc9, 0xd1, 0x31, 0x09, 0xad, 0x51,
|
||||
0x40, 0x99, 0x65, 0x8f, 0xb0, 0x3d, 0xd6, 0xae, 0x4b, 0x99, 0x9f, 0xc5, 0x5d, 0x17, 0x9c, 0xa3,
|
||||
0x31, 0x09, 0x5f, 0x06, 0x94, 0x49, 0x42, 0x79, 0xd7, 0xb5, 0xde, 0x95, 0xbb, 0x7e, 0x0f, 0x27,
|
||||
0x9d, 0x1a, 0xf5, 0x22, 0xe6, 0x25, 0xf8, 0xb9, 0x80, 0xd5, 0x3f, 0x15, 0xf0, 0xc5, 0xe2, 0x9b,
|
||||
0xbb, 0x6e, 0x70, 0x6a, 0x9d, 0x44, 0xc8, 0xc3, 0x96, 0x1b, 0x20, 0x47, 0x0c, 0xe9, 0x86, 0xac,
|
||||
0xfe, 0xc7, 0x84, 0xc3, 0xdb, 0xe5, 0xd7, 0x11, 0xb4, 0x17, 0x82, 0x75, 0x90, 0x91, 0x52, 0x0e,
|
||||
0x1f, 0x54, 0x17, 0x60, 0x95, 0x51, 0xed, 0xe2, 0xfe, 0x07, 0xf0, 0xcc, 0xab, 0xe5, 0xd4, 0x5f,
|
||||
0x14, 0x70, 0x8b, 0x62, 0xdf, 0xb1, 0x06, 0x88, 0x12, 0xdb, 0x92, 0x17, 0x1f, 0x46, 0x81, 0x17,
|
||||
0x32, 0xad, 0x23, 0xcb, 0x3d, 0x16, 0x9b, 0x2a, 0x18, 0x7b, 0x82, 0x20, 0x0e, 0xff, 0x50, 0xba,
|
||||
0x53, 0x0e, 0x75, 0x59, 0x68, 0x8d, 0xaf, 0xfc, 0xce, 0xda, 0x55, 0x4e, 0xb3, 0x2e, 0xe5, 0xde,
|
||||
0xfe, 0x9b, 0xb7, 0x7a, 0x63, 0xf6, 0x56, 0x6f, 0xbc, 0x99, 0xeb, 0xca, 0x6c, 0xae, 0x2b, 0xbf,
|
||||
0x5e, 0xe8, 0x8d, 0x3f, 0x2e, 0x74, 0x65, 0x76, 0xa1, 0x37, 0xfe, 0xb9, 0xd0, 0x1b, 0xaf, 0x1f,
|
||||
0x0c, 0x09, 0x1b, 0xc5, 0x83, 0x9e, 0x1d, 0x78, 0xdb, 0x74, 0xe2, 0xdb, 0x6c, 0x44, 0xfc, 0xe1,
|
||||
0xd2, 0x6b, 0xf1, 0x3b, 0x1d, 0x34, 0xe5, 0xbf, 0xf3, 0xc9, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff,
|
||||
0xfe, 0x19, 0xb2, 0x3c, 0x8e, 0x07, 0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *GUIConfiguration) Marshal() (dAtA []byte, err error) {
|
||||
size := m.ProtoSize()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *GUIConfiguration) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.ProtoSize()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *GUIConfiguration) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.SendBasicAuthPrompt {
|
||||
i--
|
||||
if m.SendBasicAuthPrompt {
|
||||
dAtA[i] = 1
|
||||
} else {
|
||||
dAtA[i] = 0
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x70
|
||||
}
|
||||
if m.InsecureAllowFrameLoading {
|
||||
i--
|
||||
if m.InsecureAllowFrameLoading {
|
||||
dAtA[i] = 1
|
||||
} else {
|
||||
dAtA[i] = 0
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x68
|
||||
}
|
||||
if m.InsecureSkipHostCheck {
|
||||
i--
|
||||
if m.InsecureSkipHostCheck {
|
||||
dAtA[i] = 1
|
||||
} else {
|
||||
dAtA[i] = 0
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x60
|
||||
}
|
||||
if m.Debugging {
|
||||
i--
|
||||
if m.Debugging {
|
||||
dAtA[i] = 1
|
||||
} else {
|
||||
dAtA[i] = 0
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x58
|
||||
}
|
||||
if len(m.Theme) > 0 {
|
||||
i -= len(m.Theme)
|
||||
copy(dAtA[i:], m.Theme)
|
||||
i = encodeVarintGuiconfiguration(dAtA, i, uint64(len(m.Theme)))
|
||||
i--
|
||||
dAtA[i] = 0x52
|
||||
}
|
||||
if m.InsecureAdminAccess {
|
||||
i--
|
||||
if m.InsecureAdminAccess {
|
||||
dAtA[i] = 1
|
||||
} else {
|
||||
dAtA[i] = 0
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x48
|
||||
}
|
||||
if len(m.APIKey) > 0 {
|
||||
i -= len(m.APIKey)
|
||||
copy(dAtA[i:], m.APIKey)
|
||||
i = encodeVarintGuiconfiguration(dAtA, i, uint64(len(m.APIKey)))
|
||||
i--
|
||||
dAtA[i] = 0x42
|
||||
}
|
||||
if m.RawUseTLS {
|
||||
i--
|
||||
if m.RawUseTLS {
|
||||
dAtA[i] = 1
|
||||
} else {
|
||||
dAtA[i] = 0
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x38
|
||||
}
|
||||
if m.AuthMode != 0 {
|
||||
i = encodeVarintGuiconfiguration(dAtA, i, uint64(m.AuthMode))
|
||||
i--
|
||||
dAtA[i] = 0x30
|
||||
}
|
||||
if len(m.Password) > 0 {
|
||||
i -= len(m.Password)
|
||||
copy(dAtA[i:], m.Password)
|
||||
i = encodeVarintGuiconfiguration(dAtA, i, uint64(len(m.Password)))
|
||||
i--
|
||||
dAtA[i] = 0x2a
|
||||
}
|
||||
if len(m.User) > 0 {
|
||||
i -= len(m.User)
|
||||
copy(dAtA[i:], m.User)
|
||||
i = encodeVarintGuiconfiguration(dAtA, i, uint64(len(m.User)))
|
||||
i--
|
||||
dAtA[i] = 0x22
|
||||
}
|
||||
if len(m.RawUnixSocketPermissions) > 0 {
|
||||
i -= len(m.RawUnixSocketPermissions)
|
||||
copy(dAtA[i:], m.RawUnixSocketPermissions)
|
||||
i = encodeVarintGuiconfiguration(dAtA, i, uint64(len(m.RawUnixSocketPermissions)))
|
||||
i--
|
||||
dAtA[i] = 0x1a
|
||||
}
|
||||
if len(m.RawAddress) > 0 {
|
||||
i -= len(m.RawAddress)
|
||||
copy(dAtA[i:], m.RawAddress)
|
||||
i = encodeVarintGuiconfiguration(dAtA, i, uint64(len(m.RawAddress)))
|
||||
i--
|
||||
dAtA[i] = 0x12
|
||||
}
|
||||
if m.Enabled {
|
||||
i--
|
||||
if m.Enabled {
|
||||
dAtA[i] = 1
|
||||
} else {
|
||||
dAtA[i] = 0
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x8
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func encodeVarintGuiconfiguration(dAtA []byte, offset int, v uint64) int {
|
||||
offset -= sovGuiconfiguration(v)
|
||||
base := offset
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return base
|
||||
}
|
||||
func (m *GUIConfiguration) ProtoSize() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
if m.Enabled {
|
||||
n += 2
|
||||
}
|
||||
l = len(m.RawAddress)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovGuiconfiguration(uint64(l))
|
||||
}
|
||||
l = len(m.RawUnixSocketPermissions)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovGuiconfiguration(uint64(l))
|
||||
}
|
||||
l = len(m.User)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovGuiconfiguration(uint64(l))
|
||||
}
|
||||
l = len(m.Password)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovGuiconfiguration(uint64(l))
|
||||
}
|
||||
if m.AuthMode != 0 {
|
||||
n += 1 + sovGuiconfiguration(uint64(m.AuthMode))
|
||||
}
|
||||
if m.RawUseTLS {
|
||||
n += 2
|
||||
}
|
||||
l = len(m.APIKey)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovGuiconfiguration(uint64(l))
|
||||
}
|
||||
if m.InsecureAdminAccess {
|
||||
n += 2
|
||||
}
|
||||
l = len(m.Theme)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovGuiconfiguration(uint64(l))
|
||||
}
|
||||
if m.Debugging {
|
||||
n += 2
|
||||
}
|
||||
if m.InsecureSkipHostCheck {
|
||||
n += 2
|
||||
}
|
||||
if m.InsecureAllowFrameLoading {
|
||||
n += 2
|
||||
}
|
||||
if m.SendBasicAuthPrompt {
|
||||
n += 2
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovGuiconfiguration(x uint64) (n int) {
|
||||
return (math_bits.Len64(x|1) + 6) / 7
|
||||
}
|
||||
func sozGuiconfiguration(x uint64) (n int) {
|
||||
return sovGuiconfiguration(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (m *GUIConfiguration) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGuiconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: GUIConfiguration: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: GUIConfiguration: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Enabled", wireType)
|
||||
}
|
||||
var v int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGuiconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
v |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
m.Enabled = bool(v != 0)
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field RawAddress", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGuiconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthGuiconfiguration
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthGuiconfiguration
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.RawAddress = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field RawUnixSocketPermissions", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGuiconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthGuiconfiguration
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthGuiconfiguration
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.RawUnixSocketPermissions = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 4:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field User", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGuiconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthGuiconfiguration
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthGuiconfiguration
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.User = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 5:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Password", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGuiconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthGuiconfiguration
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthGuiconfiguration
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Password = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 6:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field AuthMode", wireType)
|
||||
}
|
||||
m.AuthMode = 0
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGuiconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.AuthMode |= AuthMode(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 7:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field RawUseTLS", wireType)
|
||||
}
|
||||
var v int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGuiconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
v |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
m.RawUseTLS = bool(v != 0)
|
||||
case 8:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field APIKey", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGuiconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthGuiconfiguration
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthGuiconfiguration
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.APIKey = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 9:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field InsecureAdminAccess", wireType)
|
||||
}
|
||||
var v int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGuiconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
v |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
m.InsecureAdminAccess = bool(v != 0)
|
||||
case 10:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Theme", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGuiconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthGuiconfiguration
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthGuiconfiguration
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Theme = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 11:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Debugging", wireType)
|
||||
}
|
||||
var v int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGuiconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
v |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
m.Debugging = bool(v != 0)
|
||||
case 12:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field InsecureSkipHostCheck", wireType)
|
||||
}
|
||||
var v int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGuiconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
v |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
m.InsecureSkipHostCheck = bool(v != 0)
|
||||
case 13:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field InsecureAllowFrameLoading", wireType)
|
||||
}
|
||||
var v int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGuiconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
v |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
m.InsecureAllowFrameLoading = bool(v != 0)
|
||||
case 14:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field SendBasicAuthPrompt", wireType)
|
||||
}
|
||||
var v int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGuiconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
v |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
m.SendBasicAuthPrompt = bool(v != 0)
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipGuiconfiguration(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthGuiconfiguration
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipGuiconfiguration(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
depth := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGuiconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGuiconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if dAtA[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGuiconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthGuiconfiguration
|
||||
}
|
||||
iNdEx += length
|
||||
case 3:
|
||||
depth++
|
||||
case 4:
|
||||
if depth == 0 {
|
||||
return 0, ErrUnexpectedEndOfGroupGuiconfiguration
|
||||
}
|
||||
depth--
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
if iNdEx < 0 {
|
||||
return 0, ErrInvalidLengthGuiconfiguration
|
||||
}
|
||||
if depth == 0 {
|
||||
return iNdEx, nil
|
||||
}
|
||||
}
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthGuiconfiguration = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowGuiconfiguration = fmt.Errorf("proto: integer overflow")
|
||||
ErrUnexpectedEndOfGroupGuiconfiguration = fmt.Errorf("proto: unexpected end of group")
|
||||
)
|
||||
@@ -6,6 +6,15 @@
|
||||
|
||||
package config
|
||||
|
||||
type LDAPConfiguration struct {
|
||||
Address string `json:"address" xml:"address,omitempty"`
|
||||
BindDN string `json:"bindDN" xml:"bindDN,omitempty"`
|
||||
Transport LDAPTransport `json:"transport" xml:"transport,omitempty"`
|
||||
InsecureSkipVerify bool `json:"insecureSkipVerify" xml:"insecureSkipVerify,omitempty" default:"false"`
|
||||
SearchBaseDN string `json:"searchBaseDN" xml:"searchBaseDN,omitempty"`
|
||||
SearchFilter string `json:"searchFilter" xml:"searchFilter,omitempty"`
|
||||
}
|
||||
|
||||
func (c LDAPConfiguration) Copy() LDAPConfiguration {
|
||||
return c
|
||||
}
|
||||
|
||||
@@ -1,526 +0,0 @@
|
||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: lib/config/ldapconfiguration.proto
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
_ "github.com/syncthing/syncthing/proto/ext"
|
||||
io "io"
|
||||
math "math"
|
||||
math_bits "math/bits"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
type LDAPConfiguration struct {
|
||||
Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address" xml:"address,omitempty"`
|
||||
BindDN string `protobuf:"bytes,2,opt,name=bind_dn,json=bindDn,proto3" json:"bindDN" xml:"bindDN,omitempty"`
|
||||
Transport LDAPTransport `protobuf:"varint,3,opt,name=transport,proto3,enum=config.LDAPTransport" json:"transport" xml:"transport,omitempty"`
|
||||
InsecureSkipVerify bool `protobuf:"varint,4,opt,name=insecure_skip_verify,json=insecureSkipVerify,proto3" json:"insecureSkipVerify" xml:"insecureSkipVerify,omitempty" default:"false"`
|
||||
SearchBaseDN string `protobuf:"bytes,5,opt,name=search_base_dn,json=searchBaseDn,proto3" json:"searchBaseDN" xml:"searchBaseDN,omitempty"`
|
||||
SearchFilter string `protobuf:"bytes,6,opt,name=search_filter,json=searchFilter,proto3" json:"searchFilter" xml:"searchFilter,omitempty"`
|
||||
}
|
||||
|
||||
func (m *LDAPConfiguration) Reset() { *m = LDAPConfiguration{} }
|
||||
func (m *LDAPConfiguration) String() string { return proto.CompactTextString(m) }
|
||||
func (*LDAPConfiguration) ProtoMessage() {}
|
||||
func (*LDAPConfiguration) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_9681ad7e41c73956, []int{0}
|
||||
}
|
||||
func (m *LDAPConfiguration) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *LDAPConfiguration) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_LDAPConfiguration.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *LDAPConfiguration) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_LDAPConfiguration.Merge(m, src)
|
||||
}
|
||||
func (m *LDAPConfiguration) XXX_Size() int {
|
||||
return m.ProtoSize()
|
||||
}
|
||||
func (m *LDAPConfiguration) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_LDAPConfiguration.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_LDAPConfiguration proto.InternalMessageInfo
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*LDAPConfiguration)(nil), "config.LDAPConfiguration")
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("lib/config/ldapconfiguration.proto", fileDescriptor_9681ad7e41c73956)
|
||||
}
|
||||
|
||||
var fileDescriptor_9681ad7e41c73956 = []byte{
|
||||
// 500 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x53, 0xbf, 0x6f, 0xd3, 0x40,
|
||||
0x14, 0xb6, 0x81, 0xba, 0xc4, 0x2a, 0x15, 0x35, 0x50, 0x4c, 0x55, 0xf9, 0x22, 0xcb, 0x43, 0x90,
|
||||
0x50, 0x22, 0x95, 0xad, 0x4c, 0x35, 0x15, 0x03, 0x20, 0x84, 0x5c, 0xe8, 0xc0, 0x12, 0xf9, 0xc7,
|
||||
0x39, 0x39, 0xd5, 0x39, 0x5b, 0x77, 0xe7, 0xaa, 0xe1, 0xaf, 0x80, 0xfe, 0x05, 0xdd, 0xf8, 0x57,
|
||||
0xba, 0xc5, 0x23, 0xd3, 0x49, 0x4d, 0x36, 0x8f, 0x1e, 0x99, 0x50, 0xce, 0x4e, 0x63, 0xa7, 0x51,
|
||||
0xb7, 0xf7, 0xbe, 0xef, 0xbd, 0xef, 0x7d, 0x77, 0x4f, 0x4f, 0x35, 0x23, 0xe4, 0xf5, 0xfc, 0x18,
|
||||
0x87, 0x68, 0xd0, 0x8b, 0x02, 0x37, 0x29, 0xc3, 0x94, 0xb8, 0x0c, 0xc5, 0xb8, 0x9b, 0x90, 0x98,
|
||||
0xc5, 0x9a, 0x52, 0x82, 0x7b, 0xc6, 0x4a, 0x2d, 0x23, 0x2e, 0xa6, 0x49, 0x4c, 0x58, 0x59, 0xb7,
|
||||
0xd7, 0x82, 0x17, 0x55, 0x68, 0xfe, 0x56, 0xd4, 0x9d, 0xcf, 0xc7, 0x47, 0x5f, 0xdf, 0xd7, 0xe5,
|
||||
0xb4, 0xef, 0xea, 0xa6, 0x1b, 0x04, 0x04, 0x52, 0xaa, 0xcb, 0x6d, 0xb9, 0xd3, 0xb2, 0xdf, 0xe5,
|
||||
0x1c, 0x2c, 0xa0, 0x82, 0x83, 0x97, 0x17, 0xa3, 0xe8, 0xd0, 0xac, 0xf2, 0x37, 0xf1, 0x08, 0x31,
|
||||
0x38, 0x4a, 0xd8, 0xd8, 0xcc, 0x27, 0xd6, 0xce, 0x1d, 0xd4, 0x59, 0x34, 0x6a, 0xb1, 0xba, 0xe9,
|
||||
0x21, 0x1c, 0xf4, 0x03, 0xac, 0x3f, 0x10, 0xb2, 0xa7, 0x53, 0x0e, 0x14, 0x1b, 0xe1, 0xe0, 0xf8,
|
||||
0x4b, 0xce, 0x81, 0xe2, 0x89, 0xa8, 0xe0, 0x60, 0x57, 0xe8, 0x97, 0x69, 0x53, 0xfe, 0xe9, 0x2a,
|
||||
0x58, 0x4c, 0xac, 0xaa, 0xef, 0x32, 0xb3, 0x2a, 0x2d, 0xa7, 0x44, 0xb0, 0x76, 0xae, 0xb6, 0x6e,
|
||||
0xdf, 0xae, 0x3f, 0x6c, 0xcb, 0x9d, 0xed, 0x83, 0x17, 0xdd, 0xf2, 0x63, 0xba, 0xf3, 0x57, 0x7f,
|
||||
0x5b, 0x90, 0xf6, 0x51, 0xce, 0xc1, 0xb2, 0xb6, 0xe0, 0xe0, 0x95, 0xb0, 0x70, 0x8b, 0x34, 0x5d,
|
||||
0x3c, 0x5b, 0x83, 0x3b, 0xcb, 0x76, 0xed, 0x8f, 0xac, 0x3e, 0x47, 0x98, 0x42, 0x3f, 0x25, 0xb0,
|
||||
0x4f, 0xcf, 0x50, 0xd2, 0x3f, 0x87, 0x04, 0x85, 0x63, 0xfd, 0x51, 0x5b, 0xee, 0x3c, 0xb6, 0xd3,
|
||||
0x9c, 0x03, 0x6d, 0xc1, 0x9f, 0x9c, 0xa1, 0xe4, 0x54, 0xb0, 0x05, 0x07, 0x07, 0x62, 0xea, 0x5d,
|
||||
0xaa, 0x36, 0xbe, 0x1d, 0xc0, 0xd0, 0x4d, 0x23, 0x76, 0x68, 0x86, 0x6e, 0x44, 0xe1, 0xdc, 0xce,
|
||||
0xfe, 0x7d, 0x0d, 0xff, 0x26, 0xd6, 0x86, 0xa8, 0x74, 0xd6, 0x8c, 0xd4, 0xae, 0x64, 0x75, 0x9b,
|
||||
0x42, 0x97, 0xf8, 0xc3, 0xbe, 0xe7, 0x52, 0x38, 0x5f, 0xcd, 0x86, 0x58, 0xcd, 0xcf, 0x29, 0x07,
|
||||
0x5b, 0x27, 0x82, 0xb1, 0x5d, 0x0a, 0xc5, 0x82, 0xb6, 0x68, 0x2d, 0x2f, 0x38, 0xd8, 0x17, 0x6e,
|
||||
0xeb, 0x60, 0xf3, 0x9b, 0x76, 0xd7, 0x53, 0xc5, 0xc4, 0x6a, 0x28, 0x5d, 0x66, 0x56, 0x63, 0x92,
|
||||
0x53, 0x67, 0xb1, 0x16, 0xab, 0x4f, 0x2a, 0x87, 0x21, 0x8a, 0x18, 0x24, 0xba, 0x22, 0x0c, 0x7e,
|
||||
0x5c, 0x1a, 0xfa, 0x20, 0xf0, 0x15, 0x43, 0x25, 0xb8, 0xd6, 0xd0, 0x2a, 0xe5, 0x34, 0x74, 0xec,
|
||||
0x4f, 0xd7, 0x37, 0x86, 0x94, 0xdd, 0x18, 0xd2, 0xf5, 0xd4, 0x90, 0xb3, 0xa9, 0x21, 0xff, 0x9a,
|
||||
0x19, 0xd2, 0xd5, 0xcc, 0x90, 0xb3, 0x99, 0x21, 0xfd, 0x9d, 0x19, 0xd2, 0x8f, 0xd7, 0x03, 0xc4,
|
||||
0x86, 0xa9, 0xd7, 0xf5, 0xe3, 0x51, 0x8f, 0x8e, 0xb1, 0xcf, 0x86, 0x08, 0x0f, 0x6a, 0xd1, 0xf2,
|
||||
0xfe, 0x3c, 0x45, 0xdc, 0xd9, 0xdb, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0xbf, 0x64, 0x4b, 0x05,
|
||||
0xc0, 0x03, 0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *LDAPConfiguration) Marshal() (dAtA []byte, err error) {
|
||||
size := m.ProtoSize()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *LDAPConfiguration) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.ProtoSize()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *LDAPConfiguration) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.SearchFilter) > 0 {
|
||||
i -= len(m.SearchFilter)
|
||||
copy(dAtA[i:], m.SearchFilter)
|
||||
i = encodeVarintLdapconfiguration(dAtA, i, uint64(len(m.SearchFilter)))
|
||||
i--
|
||||
dAtA[i] = 0x32
|
||||
}
|
||||
if len(m.SearchBaseDN) > 0 {
|
||||
i -= len(m.SearchBaseDN)
|
||||
copy(dAtA[i:], m.SearchBaseDN)
|
||||
i = encodeVarintLdapconfiguration(dAtA, i, uint64(len(m.SearchBaseDN)))
|
||||
i--
|
||||
dAtA[i] = 0x2a
|
||||
}
|
||||
if m.InsecureSkipVerify {
|
||||
i--
|
||||
if m.InsecureSkipVerify {
|
||||
dAtA[i] = 1
|
||||
} else {
|
||||
dAtA[i] = 0
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x20
|
||||
}
|
||||
if m.Transport != 0 {
|
||||
i = encodeVarintLdapconfiguration(dAtA, i, uint64(m.Transport))
|
||||
i--
|
||||
dAtA[i] = 0x18
|
||||
}
|
||||
if len(m.BindDN) > 0 {
|
||||
i -= len(m.BindDN)
|
||||
copy(dAtA[i:], m.BindDN)
|
||||
i = encodeVarintLdapconfiguration(dAtA, i, uint64(len(m.BindDN)))
|
||||
i--
|
||||
dAtA[i] = 0x12
|
||||
}
|
||||
if len(m.Address) > 0 {
|
||||
i -= len(m.Address)
|
||||
copy(dAtA[i:], m.Address)
|
||||
i = encodeVarintLdapconfiguration(dAtA, i, uint64(len(m.Address)))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func encodeVarintLdapconfiguration(dAtA []byte, offset int, v uint64) int {
|
||||
offset -= sovLdapconfiguration(v)
|
||||
base := offset
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return base
|
||||
}
|
||||
func (m *LDAPConfiguration) ProtoSize() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
l = len(m.Address)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovLdapconfiguration(uint64(l))
|
||||
}
|
||||
l = len(m.BindDN)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovLdapconfiguration(uint64(l))
|
||||
}
|
||||
if m.Transport != 0 {
|
||||
n += 1 + sovLdapconfiguration(uint64(m.Transport))
|
||||
}
|
||||
if m.InsecureSkipVerify {
|
||||
n += 2
|
||||
}
|
||||
l = len(m.SearchBaseDN)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovLdapconfiguration(uint64(l))
|
||||
}
|
||||
l = len(m.SearchFilter)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovLdapconfiguration(uint64(l))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovLdapconfiguration(x uint64) (n int) {
|
||||
return (math_bits.Len64(x|1) + 6) / 7
|
||||
}
|
||||
func sozLdapconfiguration(x uint64) (n int) {
|
||||
return sovLdapconfiguration(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (m *LDAPConfiguration) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowLdapconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: LDAPConfiguration: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: LDAPConfiguration: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowLdapconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthLdapconfiguration
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthLdapconfiguration
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Address = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field BindDN", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowLdapconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthLdapconfiguration
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthLdapconfiguration
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.BindDN = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Transport", wireType)
|
||||
}
|
||||
m.Transport = 0
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowLdapconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.Transport |= LDAPTransport(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 4:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field InsecureSkipVerify", wireType)
|
||||
}
|
||||
var v int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowLdapconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
v |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
m.InsecureSkipVerify = bool(v != 0)
|
||||
case 5:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field SearchBaseDN", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowLdapconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthLdapconfiguration
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthLdapconfiguration
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.SearchBaseDN = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 6:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field SearchFilter", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowLdapconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthLdapconfiguration
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthLdapconfiguration
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.SearchFilter = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipLdapconfiguration(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthLdapconfiguration
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipLdapconfiguration(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
depth := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowLdapconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowLdapconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if dAtA[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowLdapconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthLdapconfiguration
|
||||
}
|
||||
iNdEx += length
|
||||
case 3:
|
||||
depth++
|
||||
case 4:
|
||||
if depth == 0 {
|
||||
return 0, ErrUnexpectedEndOfGroupLdapconfiguration
|
||||
}
|
||||
depth--
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
if iNdEx < 0 {
|
||||
return 0, ErrInvalidLengthLdapconfiguration
|
||||
}
|
||||
if depth == 0 {
|
||||
return iNdEx, nil
|
||||
}
|
||||
}
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthLdapconfiguration = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowLdapconfiguration = fmt.Errorf("proto: integer overflow")
|
||||
ErrUnexpectedEndOfGroupLdapconfiguration = fmt.Errorf("proto: unexpected end of group")
|
||||
)
|
||||
@@ -6,6 +6,14 @@
|
||||
|
||||
package config
|
||||
|
||||
type LDAPTransport int32
|
||||
|
||||
const (
|
||||
LDAPTransportPlain LDAPTransport = 0
|
||||
LDAPTransportTLS LDAPTransport = 2
|
||||
LDAPTransportStartTLS LDAPTransport = 3
|
||||
)
|
||||
|
||||
func (t LDAPTransport) String() string {
|
||||
switch t {
|
||||
case LDAPTransportPlain:
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: lib/config/ldaptransport.proto
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
_ "github.com/gogo/protobuf/gogoproto"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
_ "github.com/syncthing/syncthing/proto/ext"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
type LDAPTransport int32
|
||||
|
||||
const (
|
||||
LDAPTransportPlain LDAPTransport = 0
|
||||
LDAPTransportTLS LDAPTransport = 2
|
||||
LDAPTransportStartTLS LDAPTransport = 3
|
||||
)
|
||||
|
||||
var LDAPTransport_name = map[int32]string{
|
||||
0: "LDAP_TRANSPORT_PLAIN",
|
||||
2: "LDAP_TRANSPORT_TLS",
|
||||
3: "LDAP_TRANSPORT_START_TLS",
|
||||
}
|
||||
|
||||
var LDAPTransport_value = map[string]int32{
|
||||
"LDAP_TRANSPORT_PLAIN": 0,
|
||||
"LDAP_TRANSPORT_TLS": 2,
|
||||
"LDAP_TRANSPORT_START_TLS": 3,
|
||||
}
|
||||
|
||||
func (LDAPTransport) EnumDescriptor() ([]byte, []int) {
|
||||
return fileDescriptor_79795fc8505b82bf, []int{0}
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterEnum("config.LDAPTransport", LDAPTransport_name, LDAPTransport_value)
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("lib/config/ldaptransport.proto", fileDescriptor_79795fc8505b82bf) }
|
||||
|
||||
var fileDescriptor_79795fc8505b82bf = []byte{
|
||||
// 273 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xcb, 0xc9, 0x4c, 0xd2,
|
||||
0x4f, 0xce, 0xcf, 0x4b, 0xcb, 0x4c, 0xd7, 0xcf, 0x49, 0x49, 0x2c, 0x28, 0x29, 0x4a, 0xcc, 0x2b,
|
||||
0x2e, 0xc8, 0x2f, 0x2a, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x83, 0xc8, 0x49, 0x29,
|
||||
0x17, 0xa5, 0x16, 0xe4, 0x17, 0xeb, 0x83, 0x05, 0x93, 0x4a, 0xd3, 0xf4, 0xd3, 0xf3, 0xd3, 0xf3,
|
||||
0xc1, 0x1c, 0x30, 0x0b, 0xa2, 0x58, 0x8a, 0x33, 0xb5, 0x02, 0xaa, 0x4f, 0xeb, 0x23, 0x23, 0x17,
|
||||
0xaf, 0x8f, 0x8b, 0x63, 0x40, 0x08, 0xcc, 0x3c, 0x21, 0x37, 0x2e, 0x11, 0x90, 0x40, 0x7c, 0x48,
|
||||
0x90, 0xa3, 0x5f, 0x70, 0x80, 0x7f, 0x50, 0x48, 0x7c, 0x80, 0x8f, 0xa3, 0xa7, 0x9f, 0x00, 0x83,
|
||||
0x94, 0x4e, 0xd7, 0x5c, 0x05, 0x21, 0x14, 0xc5, 0x01, 0x39, 0x89, 0x99, 0x79, 0x97, 0xfa, 0x54,
|
||||
0xb1, 0x88, 0x0a, 0x39, 0x70, 0x09, 0xa1, 0x99, 0x13, 0xe2, 0x13, 0x2c, 0xc0, 0x24, 0xa5, 0xd1,
|
||||
0x35, 0x57, 0x41, 0x00, 0x45, 0x7d, 0x88, 0x4f, 0xf0, 0xa5, 0x3e, 0x55, 0x0c, 0x31, 0xa1, 0x00,
|
||||
0x2e, 0x09, 0x34, 0x13, 0x82, 0x43, 0x1c, 0xa1, 0xe6, 0x30, 0x4b, 0x19, 0x75, 0xcd, 0x55, 0x10,
|
||||
0x45, 0xd1, 0x13, 0x5c, 0x92, 0x08, 0x33, 0x0c, 0xbb, 0x84, 0x14, 0xcb, 0x8a, 0x25, 0x72, 0x0c,
|
||||
0x4e, 0xde, 0x27, 0x1e, 0xca, 0x31, 0x5c, 0x78, 0x28, 0xc7, 0x70, 0xe2, 0x91, 0x1c, 0xe3, 0x85,
|
||||
0x47, 0x72, 0x8c, 0x13, 0x1e, 0xcb, 0x31, 0x2c, 0x78, 0x2c, 0xc7, 0x78, 0xe1, 0xb1, 0x1c, 0xc3,
|
||||
0x8d, 0xc7, 0x72, 0x0c, 0x51, 0x9a, 0xe9, 0x99, 0x25, 0x19, 0xa5, 0x49, 0x7a, 0xc9, 0xf9, 0xb9,
|
||||
0xfa, 0xc5, 0x95, 0x79, 0xc9, 0x25, 0x19, 0x99, 0x79, 0xe9, 0x48, 0x2c, 0x44, 0x64, 0x24, 0xb1,
|
||||
0x81, 0xc3, 0xd1, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0xc1, 0x56, 0xde, 0x17, 0xa1, 0x01, 0x00,
|
||||
0x00,
|
||||
}
|
||||
@@ -114,7 +114,7 @@ func migrateToConfigV35(cfg *Configuration) {
|
||||
for i, fcfg := range cfg.Folders {
|
||||
params := fcfg.Versioning.Params
|
||||
if params["fsType"] != "" {
|
||||
var fsType fs.FilesystemType
|
||||
var fsType FilesystemType
|
||||
_ = fsType.UnmarshalText([]byte(params["fsType"]))
|
||||
cfg.Folders[i].Versioning.FSType = fsType
|
||||
}
|
||||
@@ -228,7 +228,7 @@ func migrateToConfigV23(cfg *Configuration) {
|
||||
|
||||
func migrateToConfigV22(cfg *Configuration) {
|
||||
for i := range cfg.Folders {
|
||||
cfg.Folders[i].FilesystemType = fs.FilesystemTypeBasic
|
||||
cfg.Folders[i].FilesystemType = FilesystemTypeBasic
|
||||
// Migrate to templated external versioner commands
|
||||
if cfg.Folders[i].Versioning.Type == "external" {
|
||||
cfg.Folders[i].Versioning.Params["command"] += " %FOLDER_PATH% %FILE_PATH%"
|
||||
@@ -238,7 +238,7 @@ func migrateToConfigV22(cfg *Configuration) {
|
||||
|
||||
func migrateToConfigV21(cfg *Configuration) {
|
||||
for _, folder := range cfg.Folders {
|
||||
if folder.FilesystemType != fs.FilesystemTypeBasic {
|
||||
if folder.FilesystemType != FilesystemTypeBasic {
|
||||
continue
|
||||
}
|
||||
switch folder.Versioning.Type {
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
// Copyright (C) 2014 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 config
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
)
|
||||
|
||||
type ObservedFolder struct {
|
||||
Time time.Time `json:"time" xml:"time,attr"`
|
||||
ID string `json:"id" xml:"id,attr"`
|
||||
Label string `json:"label" xml:"label,attr"`
|
||||
}
|
||||
|
||||
type ObservedDevice struct {
|
||||
Time time.Time `json:"time" xml:"time,attr"`
|
||||
ID protocol.DeviceID `json:"deviceID" xml:"id,attr"`
|
||||
Name string `json:"name" xml:"name,attr"`
|
||||
Address string `json:"address" xml:"address,attr"`
|
||||
}
|
||||
@@ -1,716 +0,0 @@
|
||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: lib/config/observed.proto
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
github_com_gogo_protobuf_types "github.com/gogo/protobuf/types"
|
||||
github_com_syncthing_syncthing_lib_protocol "github.com/syncthing/syncthing/lib/protocol"
|
||||
_ "github.com/syncthing/syncthing/proto/ext"
|
||||
_ "google.golang.org/protobuf/types/known/timestamppb"
|
||||
io "io"
|
||||
math "math"
|
||||
math_bits "math/bits"
|
||||
time "time"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
var _ = time.Kitchen
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
type ObservedFolder struct {
|
||||
Time time.Time `protobuf:"bytes,1,opt,name=time,proto3,stdtime" json:"time" xml:"time,attr"`
|
||||
ID string `protobuf:"bytes,2,opt,name=id,proto3" json:"id" xml:"id,attr"`
|
||||
Label string `protobuf:"bytes,3,opt,name=label,proto3" json:"label" xml:"label,attr"`
|
||||
}
|
||||
|
||||
func (m *ObservedFolder) Reset() { *m = ObservedFolder{} }
|
||||
func (m *ObservedFolder) String() string { return proto.CompactTextString(m) }
|
||||
func (*ObservedFolder) ProtoMessage() {}
|
||||
func (*ObservedFolder) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_49f68ff7b178722f, []int{0}
|
||||
}
|
||||
func (m *ObservedFolder) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *ObservedFolder) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_ObservedFolder.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *ObservedFolder) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_ObservedFolder.Merge(m, src)
|
||||
}
|
||||
func (m *ObservedFolder) XXX_Size() int {
|
||||
return m.ProtoSize()
|
||||
}
|
||||
func (m *ObservedFolder) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_ObservedFolder.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_ObservedFolder proto.InternalMessageInfo
|
||||
|
||||
type ObservedDevice struct {
|
||||
Time time.Time `protobuf:"bytes,1,opt,name=time,proto3,stdtime" json:"time" xml:"time,attr"`
|
||||
ID github_com_syncthing_syncthing_lib_protocol.DeviceID `protobuf:"bytes,2,opt,name=id,proto3,customtype=github.com/syncthing/syncthing/lib/protocol.DeviceID" json:"deviceID" xml:"id,attr"`
|
||||
Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name" xml:"name,attr"`
|
||||
Address string `protobuf:"bytes,4,opt,name=address,proto3" json:"address" xml:"address,attr"`
|
||||
}
|
||||
|
||||
func (m *ObservedDevice) Reset() { *m = ObservedDevice{} }
|
||||
func (m *ObservedDevice) String() string { return proto.CompactTextString(m) }
|
||||
func (*ObservedDevice) ProtoMessage() {}
|
||||
func (*ObservedDevice) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_49f68ff7b178722f, []int{1}
|
||||
}
|
||||
func (m *ObservedDevice) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *ObservedDevice) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_ObservedDevice.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *ObservedDevice) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_ObservedDevice.Merge(m, src)
|
||||
}
|
||||
func (m *ObservedDevice) XXX_Size() int {
|
||||
return m.ProtoSize()
|
||||
}
|
||||
func (m *ObservedDevice) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_ObservedDevice.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_ObservedDevice proto.InternalMessageInfo
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*ObservedFolder)(nil), "config.ObservedFolder")
|
||||
proto.RegisterType((*ObservedDevice)(nil), "config.ObservedDevice")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("lib/config/observed.proto", fileDescriptor_49f68ff7b178722f) }
|
||||
|
||||
var fileDescriptor_49f68ff7b178722f = []byte{
|
||||
// 440 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x93, 0x3f, 0x6f, 0xd4, 0x30,
|
||||
0x00, 0xc5, 0xe3, 0xf4, 0x68, 0x39, 0x53, 0xfe, 0x28, 0xd3, 0x71, 0x83, 0x5d, 0x9d, 0x32, 0x1c,
|
||||
0x02, 0x25, 0xfc, 0x9b, 0x10, 0x42, 0xe2, 0x74, 0x42, 0x3a, 0x75, 0x40, 0x8a, 0x98, 0x98, 0x48,
|
||||
0x62, 0x37, 0xb5, 0x94, 0x9c, 0xab, 0xc4, 0xad, 0xca, 0xc6, 0xc8, 0xd8, 0xf2, 0x09, 0xf8, 0x38,
|
||||
0xb7, 0x5d, 0x46, 0xc4, 0x60, 0xd4, 0xcb, 0x96, 0x31, 0x12, 0x3b, 0x8a, 0x9d, 0xf8, 0x6e, 0x42,
|
||||
0x4c, 0x6c, 0x7e, 0x4f, 0xcf, 0x3f, 0xf9, 0xbd, 0x28, 0xf0, 0x61, 0xca, 0x22, 0x3f, 0xe6, 0xcb,
|
||||
0x13, 0x96, 0xf8, 0x3c, 0x2a, 0x68, 0x7e, 0x41, 0x89, 0x77, 0x96, 0x73, 0xc1, 0x9d, 0x7d, 0x6d,
|
||||
0x8f, 0x71, 0xc2, 0x79, 0x92, 0x52, 0x5f, 0xb9, 0xd1, 0xf9, 0x89, 0x2f, 0x58, 0x46, 0x0b, 0x11,
|
||||
0x66, 0x67, 0x3a, 0x38, 0x1e, 0xd2, 0x4b, 0xa1, 0x8f, 0x93, 0xdf, 0x00, 0xde, 0x7b, 0xdf, 0x61,
|
||||
0xde, 0xf1, 0x94, 0xd0, 0xdc, 0xf9, 0x04, 0x07, 0xed, 0x85, 0x11, 0x38, 0x02, 0xd3, 0x3b, 0xcf,
|
||||
0xc7, 0x9e, 0xa6, 0x79, 0x3d, 0xcd, 0xfb, 0xd0, 0xd3, 0x66, 0x4f, 0x57, 0x12, 0x5b, 0xb5, 0xc4,
|
||||
0x2a, 0xdf, 0x48, 0x7c, 0xff, 0x32, 0x4b, 0x5f, 0x4d, 0x5a, 0xf1, 0x24, 0x14, 0x22, 0x9f, 0x5c,
|
||||
0xfd, 0xc2, 0xa0, 0x5e, 0xbb, 0x43, 0xe3, 0x04, 0x2a, 0xe9, 0xbc, 0x81, 0x36, 0x23, 0x23, 0xfb,
|
||||
0x08, 0x4c, 0x87, 0x33, 0x6f, 0x23, 0xb1, 0xbd, 0x98, 0xd7, 0x12, 0xdb, 0x8c, 0x34, 0x12, 0xdf,
|
||||
0x55, 0x0c, 0x46, 0x34, 0xa1, 0x5e, 0xbb, 0x07, 0xdd, 0xf9, 0x5b, 0xe9, 0xda, 0x8b, 0x79, 0x60,
|
||||
0x33, 0xe2, 0xbc, 0x85, 0xb7, 0xd2, 0x30, 0xa2, 0xe9, 0x68, 0x4f, 0x21, 0x1e, 0xd7, 0x12, 0x6b,
|
||||
0xa3, 0x91, 0xf8, 0x81, 0xba, 0xaf, 0x94, 0x41, 0xc0, 0xad, 0x0c, 0x74, 0x70, 0x72, 0xbd, 0xb7,
|
||||
0xed, 0x3d, 0xa7, 0x17, 0x2c, 0xa6, 0xff, 0xa1, 0xf7, 0x35, 0x30, 0xc5, 0x0f, 0x67, 0x5f, 0x40,
|
||||
0x4b, 0xf9, 0x29, 0xf1, 0xcb, 0x84, 0x89, 0xd3, 0xf3, 0xc8, 0x8b, 0x79, 0xe6, 0x17, 0x9f, 0x97,
|
||||
0xb1, 0x38, 0x65, 0xcb, 0x64, 0xe7, 0xd4, 0x7e, 0x70, 0xf5, 0x88, 0x98, 0xa7, 0x9e, 0x7e, 0xeb,
|
||||
0x62, 0x6e, 0x56, 0xbb, 0x4d, 0x3a, 0xe7, 0x6f, 0xdb, 0x35, 0x6b, 0xd7, 0xe4, 0xbe, 0x96, 0x2e,
|
||||
0xd8, 0xd9, 0xf2, 0x35, 0x1c, 0x2c, 0xc3, 0x8c, 0x76, 0x53, 0x4e, 0xdb, 0x56, 0xad, 0x36, 0xad,
|
||||
0x5a, 0x61, 0x78, 0x43, 0xa3, 0x02, 0x95, 0x72, 0x8e, 0xe1, 0x41, 0x48, 0x48, 0x4e, 0x8b, 0x62,
|
||||
0x34, 0x50, 0x80, 0x67, 0xb5, 0xc4, 0xbd, 0xd5, 0x48, 0xec, 0x28, 0x46, 0xa7, 0x0d, 0xe6, 0x70,
|
||||
0xd7, 0x08, 0xfa, 0xf8, 0xec, 0x78, 0x75, 0x83, 0xac, 0xf2, 0x06, 0x59, 0xab, 0x0d, 0x02, 0xe5,
|
||||
0x06, 0x81, 0xab, 0x0a, 0x59, 0xdf, 0x2b, 0x04, 0xca, 0x0a, 0x59, 0x3f, 0x2a, 0x64, 0x7d, 0x7c,
|
||||
0xf4, 0x0f, 0x53, 0xe9, 0x9f, 0x20, 0xda, 0x57, 0x93, 0xbd, 0xf8, 0x13, 0x00, 0x00, 0xff, 0xff,
|
||||
0xd0, 0xf0, 0x82, 0x78, 0x30, 0x03, 0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *ObservedFolder) Marshal() (dAtA []byte, err error) {
|
||||
size := m.ProtoSize()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *ObservedFolder) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.ProtoSize()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *ObservedFolder) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Label) > 0 {
|
||||
i -= len(m.Label)
|
||||
copy(dAtA[i:], m.Label)
|
||||
i = encodeVarintObserved(dAtA, i, uint64(len(m.Label)))
|
||||
i--
|
||||
dAtA[i] = 0x1a
|
||||
}
|
||||
if len(m.ID) > 0 {
|
||||
i -= len(m.ID)
|
||||
copy(dAtA[i:], m.ID)
|
||||
i = encodeVarintObserved(dAtA, i, uint64(len(m.ID)))
|
||||
i--
|
||||
dAtA[i] = 0x12
|
||||
}
|
||||
n1, err1 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Time):])
|
||||
if err1 != nil {
|
||||
return 0, err1
|
||||
}
|
||||
i -= n1
|
||||
i = encodeVarintObserved(dAtA, i, uint64(n1))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *ObservedDevice) Marshal() (dAtA []byte, err error) {
|
||||
size := m.ProtoSize()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *ObservedDevice) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.ProtoSize()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *ObservedDevice) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Address) > 0 {
|
||||
i -= len(m.Address)
|
||||
copy(dAtA[i:], m.Address)
|
||||
i = encodeVarintObserved(dAtA, i, uint64(len(m.Address)))
|
||||
i--
|
||||
dAtA[i] = 0x22
|
||||
}
|
||||
if len(m.Name) > 0 {
|
||||
i -= len(m.Name)
|
||||
copy(dAtA[i:], m.Name)
|
||||
i = encodeVarintObserved(dAtA, i, uint64(len(m.Name)))
|
||||
i--
|
||||
dAtA[i] = 0x1a
|
||||
}
|
||||
{
|
||||
size := m.ID.ProtoSize()
|
||||
i -= size
|
||||
if _, err := m.ID.MarshalTo(dAtA[i:]); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i = encodeVarintObserved(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x12
|
||||
n2, err2 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Time):])
|
||||
if err2 != nil {
|
||||
return 0, err2
|
||||
}
|
||||
i -= n2
|
||||
i = encodeVarintObserved(dAtA, i, uint64(n2))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func encodeVarintObserved(dAtA []byte, offset int, v uint64) int {
|
||||
offset -= sovObserved(v)
|
||||
base := offset
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return base
|
||||
}
|
||||
func (m *ObservedFolder) ProtoSize() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.Time)
|
||||
n += 1 + l + sovObserved(uint64(l))
|
||||
l = len(m.ID)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovObserved(uint64(l))
|
||||
}
|
||||
l = len(m.Label)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovObserved(uint64(l))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *ObservedDevice) ProtoSize() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.Time)
|
||||
n += 1 + l + sovObserved(uint64(l))
|
||||
l = m.ID.ProtoSize()
|
||||
n += 1 + l + sovObserved(uint64(l))
|
||||
l = len(m.Name)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovObserved(uint64(l))
|
||||
}
|
||||
l = len(m.Address)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovObserved(uint64(l))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovObserved(x uint64) (n int) {
|
||||
return (math_bits.Len64(x|1) + 6) / 7
|
||||
}
|
||||
func sozObserved(x uint64) (n int) {
|
||||
return sovObserved(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (m *ObservedFolder) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowObserved
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: ObservedFolder: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: ObservedFolder: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowObserved
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthObserved
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthObserved
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.Time, dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowObserved
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthObserved
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthObserved
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.ID = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Label", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowObserved
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthObserved
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthObserved
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Label = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipObserved(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthObserved
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *ObservedDevice) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowObserved
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: ObservedDevice: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: ObservedDevice: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowObserved
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthObserved
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthObserved
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.Time, dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType)
|
||||
}
|
||||
var byteLen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowObserved
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
byteLen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if byteLen < 0 {
|
||||
return ErrInvalidLengthObserved
|
||||
}
|
||||
postIndex := iNdEx + byteLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthObserved
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := m.ID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowObserved
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthObserved
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthObserved
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Name = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 4:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowObserved
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthObserved
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthObserved
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Address = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipObserved(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthObserved
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipObserved(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
depth := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowObserved
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowObserved
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if dAtA[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowObserved
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthObserved
|
||||
}
|
||||
iNdEx += length
|
||||
case 3:
|
||||
depth++
|
||||
case 4:
|
||||
if depth == 0 {
|
||||
return 0, ErrUnexpectedEndOfGroupObserved
|
||||
}
|
||||
depth--
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
if iNdEx < 0 {
|
||||
return 0, ErrInvalidLengthObserved
|
||||
}
|
||||
if depth == 0 {
|
||||
return iNdEx, nil
|
||||
}
|
||||
}
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthObserved = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowObserved = fmt.Errorf("proto: integer overflow")
|
||||
ErrUnexpectedEndOfGroupObserved = fmt.Errorf("proto: unexpected end of group")
|
||||
)
|
||||
@@ -16,6 +16,81 @@ import (
|
||||
"github.com/syncthing/syncthing/lib/structutil"
|
||||
)
|
||||
|
||||
type OptionsConfiguration struct {
|
||||
RawListenAddresses []string `json:"listenAddresses" xml:"listenAddress" default:"default"`
|
||||
RawGlobalAnnServers []string `json:"globalAnnounceServers" xml:"globalAnnounceServer" default:"default"`
|
||||
GlobalAnnEnabled bool `json:"globalAnnounceEnabled" xml:"globalAnnounceEnabled" default:"true"`
|
||||
LocalAnnEnabled bool `json:"localAnnounceEnabled" xml:"localAnnounceEnabled" default:"true"`
|
||||
LocalAnnPort int `json:"localAnnouncePort" xml:"localAnnouncePort" default:"21027"`
|
||||
LocalAnnMCAddr string `json:"localAnnounceMCAddr" xml:"localAnnounceMCAddr" default:"[ff12::8384]:21027"`
|
||||
MaxSendKbps int `json:"maxSendKbps" xml:"maxSendKbps"`
|
||||
MaxRecvKbps int `json:"maxRecvKbps" xml:"maxRecvKbps"`
|
||||
ReconnectIntervalS int `json:"reconnectionIntervalS" xml:"reconnectionIntervalS" default:"60"`
|
||||
RelaysEnabled bool `json:"relaysEnabled" xml:"relaysEnabled" default:"true"`
|
||||
RelayReconnectIntervalM int `json:"relayReconnectIntervalM" xml:"relayReconnectIntervalM" default:"10"`
|
||||
StartBrowser bool `json:"startBrowser" xml:"startBrowser" default:"true"`
|
||||
NATEnabled bool `json:"natEnabled" xml:"natEnabled" default:"true"`
|
||||
NATLeaseM int `json:"natLeaseMinutes" xml:"natLeaseMinutes" default:"60"`
|
||||
NATRenewalM int `json:"natRenewalMinutes" xml:"natRenewalMinutes" default:"30"`
|
||||
NATTimeoutS int `json:"natTimeoutSeconds" xml:"natTimeoutSeconds" default:"10"`
|
||||
URAccepted int `json:"urAccepted" xml:"urAccepted"`
|
||||
URSeen int `json:"urSeen" xml:"urSeen"`
|
||||
URUniqueID string `json:"urUniqueId" xml:"urUniqueID"`
|
||||
URURL string `json:"urURL" xml:"urURL" default:"https://data.syncthing.net/newdata"`
|
||||
URPostInsecurely bool `json:"urPostInsecurely" xml:"urPostInsecurely" default:"false"`
|
||||
URInitialDelayS int `json:"urInitialDelayS" xml:"urInitialDelayS" default:"1800"`
|
||||
AutoUpgradeIntervalH int `json:"autoUpgradeIntervalH" xml:"autoUpgradeIntervalH" default:"12"`
|
||||
UpgradeToPreReleases bool `json:"upgradeToPreReleases" xml:"upgradeToPreReleases"`
|
||||
KeepTemporariesH int `json:"keepTemporariesH" xml:"keepTemporariesH" default:"24"`
|
||||
CacheIgnoredFiles bool `json:"cacheIgnoredFiles" xml:"cacheIgnoredFiles" default:"false"`
|
||||
ProgressUpdateIntervalS int `json:"progressUpdateIntervalS" xml:"progressUpdateIntervalS" default:"5"`
|
||||
LimitBandwidthInLan bool `json:"limitBandwidthInLan" xml:"limitBandwidthInLan" default:"false"`
|
||||
MinHomeDiskFree Size `json:"minHomeDiskFree" xml:"minHomeDiskFree" default:"1 %"`
|
||||
ReleasesURL string `json:"releasesURL" xml:"releasesURL" default:"https://upgrades.syncthing.net/meta.json"`
|
||||
AlwaysLocalNets []string `json:"alwaysLocalNets" xml:"alwaysLocalNet"`
|
||||
OverwriteRemoteDevNames bool `json:"overwriteRemoteDeviceNamesOnConnect" xml:"overwriteRemoteDeviceNamesOnConnect" default:"false"`
|
||||
TempIndexMinBlocks int `json:"tempIndexMinBlocks" xml:"tempIndexMinBlocks" default:"10"`
|
||||
UnackedNotificationIDs []string `json:"unackedNotificationIDs" xml:"unackedNotificationID"`
|
||||
TrafficClass int `json:"trafficClass" xml:"trafficClass"`
|
||||
DeprecatedDefaultFolderPath string `json:"-" xml:"defaultFolderPath,omitempty"` // Deprecated: Do not use.
|
||||
SetLowPriority bool `json:"setLowPriority" xml:"setLowPriority" default:"true"`
|
||||
RawMaxFolderConcurrency int `json:"maxFolderConcurrency" xml:"maxFolderConcurrency"`
|
||||
CRURL string `json:"crURL" xml:"crashReportingURL" default:"https://crash.syncthing.net/newcrash"`
|
||||
CREnabled bool `json:"crashReportingEnabled" xml:"crashReportingEnabled" default:"true"`
|
||||
StunKeepaliveStartS int `json:"stunKeepaliveStartS" xml:"stunKeepaliveStartS" default:"180"`
|
||||
StunKeepaliveMinS int `json:"stunKeepaliveMinS" xml:"stunKeepaliveMinS" default:"20"`
|
||||
RawStunServers []string `json:"stunServers" xml:"stunServer" default:"default"`
|
||||
DatabaseTuning Tuning `json:"databaseTuning" xml:"databaseTuning" restart:"true"`
|
||||
RawMaxCIRequestKiB int `json:"maxConcurrentIncomingRequestKiB" xml:"maxConcurrentIncomingRequestKiB"`
|
||||
AnnounceLANAddresses bool `json:"announceLANAddresses" xml:"announceLANAddresses" default:"true"`
|
||||
SendFullIndexOnUpgrade bool `json:"sendFullIndexOnUpgrade" xml:"sendFullIndexOnUpgrade"`
|
||||
FeatureFlags []string `json:"featureFlags" xml:"featureFlag"`
|
||||
// The number of connections at which we stop trying to connect to more
|
||||
// devices, zero meaning no limit. Does not affect incoming connections.
|
||||
ConnectionLimitEnough int `json:"connectionLimitEnough" xml:"connectionLimitEnough"`
|
||||
// The maximum number of connections which we will allow in total, zero
|
||||
// meaning no limit. Affects incoming connections and prevents
|
||||
// attempting outgoing connections.
|
||||
ConnectionLimitMax int `json:"connectionLimitMax" xml:"connectionLimitMax"`
|
||||
// When set, this allows TLS 1.2 on sync connections, where we otherwise
|
||||
// default to TLS 1.3+ only.
|
||||
InsecureAllowOldTLSVersions bool `json:"insecureAllowOldTLSVersions" xml:"insecureAllowOldTLSVersions"`
|
||||
ConnectionPriorityTCPLAN int `json:"connectionPriorityTcpLan" xml:"connectionPriorityTcpLan" default:"10"`
|
||||
ConnectionPriorityQUICLAN int `json:"connectionPriorityQuicLan" xml:"connectionPriorityQuicLan" default:"20"`
|
||||
ConnectionPriorityTCPWAN int `json:"connectionPriorityTcpWan" xml:"connectionPriorityTcpWan" default:"30"`
|
||||
ConnectionPriorityQUICWAN int `json:"connectionPriorityQuicWan" xml:"connectionPriorityQuicWan" default:"40"`
|
||||
ConnectionPriorityRelay int `json:"connectionPriorityRelay" xml:"connectionPriorityRelay" default:"50"`
|
||||
ConnectionPriorityUpgradeThreshold int `json:"connectionPriorityUpgradeThreshold" xml:"connectionPriorityUpgradeThreshold" default:"0"`
|
||||
// Legacy deprecated
|
||||
DeprecatedUPnPEnabled bool `json:"-" xml:"upnpEnabled,omitempty"` // Deprecated: Do not use.
|
||||
DeprecatedUPnPLeaseM int `json:"-" xml:"upnpLeaseMinutes,omitempty"` // Deprecated: Do not use.
|
||||
DeprecatedUPnPRenewalM int `json:"-" xml:"upnpRenewalMinutes,omitempty"` // Deprecated: Do not use.
|
||||
DeprecatedUPnPTimeoutS int `json:"-" xml:"upnpTimeoutSeconds,omitempty"` // Deprecated: Do not use.
|
||||
DeprecatedRelayServers []string `json:"-" xml:"relayServer,omitempty"` // Deprecated: Do not use.
|
||||
DeprecatedMinHomeDiskFreePct float64 `json:"-" xml:"minHomeDiskFreePct,omitempty"` // Deprecated: Do not use.
|
||||
DeprecatedMaxConcurrentScans int `json:"-" xml:"maxConcurrentScans,omitempty"` // Deprecated: Do not use.
|
||||
}
|
||||
|
||||
func (opts OptionsConfiguration) Copy() OptionsConfiguration {
|
||||
optsCopy := opts
|
||||
optsCopy.RawListenAddresses = make([]string, len(opts.RawListenAddresses))
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,6 +6,17 @@
|
||||
|
||||
package config
|
||||
|
||||
type PullOrder int32
|
||||
|
||||
const (
|
||||
PullOrderRandom PullOrder = 0
|
||||
PullOrderAlphabetic PullOrder = 1
|
||||
PullOrderSmallestFirst PullOrder = 2
|
||||
PullOrderLargestFirst PullOrder = 3
|
||||
PullOrderOldestFirst PullOrder = 4
|
||||
PullOrderNewestFirst PullOrder = 5
|
||||
)
|
||||
|
||||
func (o PullOrder) String() string {
|
||||
switch o {
|
||||
case PullOrderRandom:
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: lib/config/pullorder.proto
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
_ "github.com/gogo/protobuf/gogoproto"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
type PullOrder int32
|
||||
|
||||
const (
|
||||
PullOrderRandom PullOrder = 0
|
||||
PullOrderAlphabetic PullOrder = 1
|
||||
PullOrderSmallestFirst PullOrder = 2
|
||||
PullOrderLargestFirst PullOrder = 3
|
||||
PullOrderOldestFirst PullOrder = 4
|
||||
PullOrderNewestFirst PullOrder = 5
|
||||
)
|
||||
|
||||
var PullOrder_name = map[int32]string{
|
||||
0: "PULL_ORDER_RANDOM",
|
||||
1: "PULL_ORDER_ALPHABETIC",
|
||||
2: "PULL_ORDER_SMALLEST_FIRST",
|
||||
3: "PULL_ORDER_LARGEST_FIRST",
|
||||
4: "PULL_ORDER_OLDEST_FIRST",
|
||||
5: "PULL_ORDER_NEWEST_FIRST",
|
||||
}
|
||||
|
||||
var PullOrder_value = map[string]int32{
|
||||
"PULL_ORDER_RANDOM": 0,
|
||||
"PULL_ORDER_ALPHABETIC": 1,
|
||||
"PULL_ORDER_SMALLEST_FIRST": 2,
|
||||
"PULL_ORDER_LARGEST_FIRST": 3,
|
||||
"PULL_ORDER_OLDEST_FIRST": 4,
|
||||
"PULL_ORDER_NEWEST_FIRST": 5,
|
||||
}
|
||||
|
||||
func (PullOrder) EnumDescriptor() ([]byte, []int) {
|
||||
return fileDescriptor_2fa3f5222a7755bf, []int{0}
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterEnum("config.PullOrder", PullOrder_name, PullOrder_value)
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("lib/config/pullorder.proto", fileDescriptor_2fa3f5222a7755bf) }
|
||||
|
||||
var fileDescriptor_2fa3f5222a7755bf = []byte{
|
||||
// 347 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0xd1, 0xbf, 0x4a, 0xc3, 0x40,
|
||||
0x1c, 0xc0, 0xf1, 0xa4, 0xd6, 0x82, 0xb7, 0x58, 0x53, 0x6b, 0xdb, 0x1b, 0x8e, 0x80, 0x93, 0x1d,
|
||||
0x1a, 0x50, 0x44, 0x1c, 0x53, 0x9b, 0x6a, 0xf1, 0xda, 0x94, 0xa4, 0x22, 0xb8, 0x94, 0x24, 0x4d,
|
||||
0xd3, 0xc0, 0x35, 0x17, 0xf2, 0x07, 0xf1, 0x15, 0x32, 0xf9, 0x02, 0x01, 0x07, 0x07, 0x1f, 0xa5,
|
||||
0x63, 0xc1, 0xc5, 0xb5, 0xcd, 0x8b, 0x88, 0x29, 0x26, 0x41, 0x70, 0xfb, 0xdd, 0x8f, 0xef, 0xe7,
|
||||
0x96, 0x1f, 0x80, 0xc4, 0xd6, 0x05, 0x83, 0x3a, 0x73, 0xdb, 0x12, 0xdc, 0x90, 0x10, 0xea, 0xcd,
|
||||
0x4c, 0xaf, 0xe3, 0x7a, 0x34, 0xa0, 0x5c, 0x65, 0xb7, 0x87, 0xa7, 0x9e, 0xe9, 0x52, 0x5f, 0x48,
|
||||
0x97, 0x7a, 0x38, 0x17, 0x2c, 0x6a, 0xd1, 0xf4, 0x91, 0x4e, 0xbb, 0xb8, 0xfd, 0x59, 0x02, 0x07,
|
||||
0xe3, 0x90, 0x10, 0xf9, 0xe7, 0x03, 0xae, 0x0d, 0x8e, 0xc6, 0x0f, 0x18, 0x4f, 0x65, 0xa5, 0x27,
|
||||
0x29, 0x53, 0x45, 0x1c, 0xf5, 0xe4, 0x61, 0x95, 0x81, 0xb5, 0x28, 0xe6, 0x0f, 0xb3, 0x4a, 0xd1,
|
||||
0x9c, 0x19, 0x5d, 0x72, 0xe7, 0xa0, 0x5e, 0x68, 0x45, 0x3c, 0xbe, 0x13, 0xbb, 0xd2, 0x64, 0x70,
|
||||
0x53, 0x65, 0x61, 0x23, 0x8a, 0xf9, 0x5a, 0xd6, 0x8b, 0xc4, 0x5d, 0x68, 0xba, 0x19, 0xd8, 0x06,
|
||||
0x77, 0x0d, 0x5a, 0x05, 0xa3, 0x0e, 0x45, 0x8c, 0x25, 0x75, 0x32, 0xed, 0x0f, 0x14, 0x75, 0x52,
|
||||
0x2d, 0x41, 0x18, 0xc5, 0xfc, 0x49, 0xe6, 0xd4, 0xa5, 0x46, 0x88, 0xe9, 0x07, 0x7d, 0xdb, 0xf3,
|
||||
0x03, 0xee, 0x0a, 0x34, 0x0b, 0x14, 0x8b, 0xca, 0x6d, 0x2e, 0xf7, 0x60, 0x2b, 0x8a, 0xf9, 0x7a,
|
||||
0x26, 0xb1, 0xe6, 0x59, 0x19, 0xbc, 0x04, 0x8d, 0x02, 0x94, 0x71, 0x2f, 0x77, 0x65, 0xd8, 0x8c,
|
||||
0x62, 0xfe, 0x38, 0x73, 0x32, 0x99, 0xfd, 0xc3, 0x46, 0xd2, 0x63, 0xce, 0xf6, 0xff, 0xb0, 0x91,
|
||||
0xf9, 0xfc, 0xcb, 0x60, 0xf9, 0xe3, 0x1d, 0x31, 0xdd, 0xfb, 0xd5, 0x06, 0x31, 0xeb, 0x0d, 0x62,
|
||||
0x56, 0x5b, 0xc4, 0xae, 0xb7, 0x88, 0x7d, 0x4d, 0x10, 0xf3, 0x96, 0x20, 0x76, 0x9d, 0x20, 0xe6,
|
||||
0x2b, 0x41, 0xcc, 0xd3, 0x99, 0x65, 0x07, 0x8b, 0x50, 0xef, 0x18, 0x74, 0x29, 0xf8, 0x2f, 0x8e,
|
||||
0x11, 0x2c, 0x6c, 0xc7, 0x2a, 0x4c, 0xf9, 0x7d, 0xf5, 0x4a, 0x7a, 0xa9, 0x8b, 0xef, 0x00, 0x00,
|
||||
0x00, 0xff, 0xff, 0x09, 0x68, 0xa0, 0x7d, 0xf4, 0x01, 0x00, 0x00,
|
||||
}
|
||||
@@ -14,6 +14,11 @@ import (
|
||||
"github.com/syncthing/syncthing/lib/fs"
|
||||
)
|
||||
|
||||
type Size struct {
|
||||
Value float64 `json:"value" xml:",chardata"`
|
||||
Unit string `json:"unit" xml:"unit,attr"`
|
||||
}
|
||||
|
||||
func ParseSize(s string) (Size, error) {
|
||||
s = strings.TrimSpace(s)
|
||||
if s == "" {
|
||||
|
||||
@@ -1,336 +0,0 @@
|
||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: lib/config/size.proto
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
encoding_binary "encoding/binary"
|
||||
fmt "fmt"
|
||||
_ "github.com/gogo/protobuf/gogoproto"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
_ "github.com/syncthing/syncthing/proto/ext"
|
||||
io "io"
|
||||
math "math"
|
||||
math_bits "math/bits"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
type Size struct {
|
||||
Value float64 `protobuf:"fixed64,1,opt,name=value,proto3" json:"value" xml:",chardata"`
|
||||
Unit string `protobuf:"bytes,2,opt,name=unit,proto3" json:"unit" xml:"unit,attr"`
|
||||
}
|
||||
|
||||
func (m *Size) Reset() { *m = Size{} }
|
||||
func (*Size) ProtoMessage() {}
|
||||
func (*Size) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_4d75cb8f619bd299, []int{0}
|
||||
}
|
||||
func (m *Size) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *Size) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_Size.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *Size) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Size.Merge(m, src)
|
||||
}
|
||||
func (m *Size) XXX_Size() int {
|
||||
return m.ProtoSize()
|
||||
}
|
||||
func (m *Size) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Size.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Size proto.InternalMessageInfo
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Size)(nil), "config.Size")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("lib/config/size.proto", fileDescriptor_4d75cb8f619bd299) }
|
||||
|
||||
var fileDescriptor_4d75cb8f619bd299 = []byte{
|
||||
// 251 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xcd, 0xc9, 0x4c, 0xd2,
|
||||
0x4f, 0xce, 0xcf, 0x4b, 0xcb, 0x4c, 0xd7, 0x2f, 0xce, 0xac, 0x4a, 0xd5, 0x2b, 0x28, 0xca, 0x2f,
|
||||
0xc9, 0x17, 0x62, 0x83, 0x08, 0x49, 0x29, 0x17, 0xa5, 0x16, 0xe4, 0x17, 0xeb, 0x83, 0x05, 0x93,
|
||||
0x4a, 0xd3, 0xf4, 0xd3, 0xf3, 0xd3, 0xf3, 0xc1, 0x1c, 0x30, 0x0b, 0xa2, 0x58, 0x8a, 0x33, 0xb5,
|
||||
0xa2, 0x04, 0xc2, 0x54, 0xea, 0x66, 0xe4, 0x62, 0x09, 0xce, 0xac, 0x4a, 0x15, 0xb2, 0xe7, 0x62,
|
||||
0x2d, 0x4b, 0xcc, 0x29, 0x4d, 0x95, 0x60, 0x54, 0x60, 0xd4, 0x60, 0x74, 0xd2, 0x7c, 0x75, 0x4f,
|
||||
0x1e, 0x22, 0xf0, 0xe9, 0x9e, 0x3c, 0x7f, 0x45, 0x6e, 0x8e, 0x95, 0x92, 0x4e, 0x72, 0x46, 0x62,
|
||||
0x51, 0x4a, 0x62, 0x49, 0xa2, 0xd2, 0xab, 0xf3, 0x2a, 0x9c, 0x70, 0x5e, 0x10, 0x44, 0x99, 0x90,
|
||||
0x0d, 0x17, 0x4b, 0x69, 0x5e, 0x66, 0x89, 0x04, 0x93, 0x02, 0xa3, 0x06, 0xa7, 0x93, 0xc6, 0xab,
|
||||
0x7b, 0xf2, 0x60, 0x3e, 0x5c, 0x3b, 0x88, 0xa3, 0x93, 0x58, 0x52, 0x52, 0x04, 0xd6, 0x0e, 0xe7,
|
||||
0x05, 0x81, 0x55, 0x59, 0xb1, 0xcc, 0x58, 0x20, 0xcf, 0xe0, 0xe4, 0x7d, 0xe2, 0xa1, 0x1c, 0xc3,
|
||||
0x85, 0x87, 0x72, 0x0c, 0x27, 0x1e, 0xc9, 0x31, 0x5e, 0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1, 0x1c,
|
||||
0xc3, 0x82, 0xc7, 0x72, 0x8c, 0x17, 0x1e, 0xcb, 0x31, 0xdc, 0x78, 0x2c, 0xc7, 0x10, 0xa5, 0x99,
|
||||
0x9e, 0x59, 0x92, 0x51, 0x9a, 0xa4, 0x97, 0x9c, 0x9f, 0xab, 0x5f, 0x5c, 0x99, 0x97, 0x5c, 0x92,
|
||||
0x91, 0x99, 0x97, 0x8e, 0xc4, 0x42, 0x84, 0x4e, 0x12, 0x1b, 0xd8, 0x87, 0xc6, 0x80, 0x00, 0x00,
|
||||
0x00, 0xff, 0xff, 0x65, 0x1e, 0xa3, 0x25, 0x32, 0x01, 0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *Size) Marshal() (dAtA []byte, err error) {
|
||||
size := m.ProtoSize()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *Size) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.ProtoSize()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *Size) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Unit) > 0 {
|
||||
i -= len(m.Unit)
|
||||
copy(dAtA[i:], m.Unit)
|
||||
i = encodeVarintSize(dAtA, i, uint64(len(m.Unit)))
|
||||
i--
|
||||
dAtA[i] = 0x12
|
||||
}
|
||||
if m.Value != 0 {
|
||||
i -= 8
|
||||
encoding_binary.LittleEndian.PutUint64(dAtA[i:], uint64(math.Float64bits(float64(m.Value))))
|
||||
i--
|
||||
dAtA[i] = 0x9
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func encodeVarintSize(dAtA []byte, offset int, v uint64) int {
|
||||
offset -= sovSize(v)
|
||||
base := offset
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return base
|
||||
}
|
||||
func (m *Size) ProtoSize() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
if m.Value != 0 {
|
||||
n += 9
|
||||
}
|
||||
l = len(m.Unit)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovSize(uint64(l))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovSize(x uint64) (n int) {
|
||||
return (math_bits.Len64(x|1) + 6) / 7
|
||||
}
|
||||
func sozSize(x uint64) (n int) {
|
||||
return sovSize(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (m *Size) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowSize
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: Size: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: Size: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 1 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType)
|
||||
}
|
||||
var v uint64
|
||||
if (iNdEx + 8) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
v = uint64(encoding_binary.LittleEndian.Uint64(dAtA[iNdEx:]))
|
||||
iNdEx += 8
|
||||
m.Value = float64(math.Float64frombits(v))
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Unit", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowSize
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthSize
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthSize
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Unit = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipSize(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthSize
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipSize(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
depth := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowSize
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowSize
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if dAtA[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowSize
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthSize
|
||||
}
|
||||
iNdEx += length
|
||||
case 3:
|
||||
depth++
|
||||
case 4:
|
||||
if depth == 0 {
|
||||
return 0, ErrUnexpectedEndOfGroupSize
|
||||
}
|
||||
depth--
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
if iNdEx < 0 {
|
||||
return 0, ErrInvalidLengthSize
|
||||
}
|
||||
if depth == 0 {
|
||||
return iNdEx, nil
|
||||
}
|
||||
}
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthSize = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowSize = fmt.Errorf("proto: integer overflow")
|
||||
ErrUnexpectedEndOfGroupSize = fmt.Errorf("proto: unexpected end of group")
|
||||
)
|
||||
@@ -6,6 +6,14 @@
|
||||
|
||||
package config
|
||||
|
||||
type Tuning int32
|
||||
|
||||
const (
|
||||
TuningAuto Tuning = 0
|
||||
TuningSmall Tuning = 1
|
||||
TuningLarge Tuning = 2
|
||||
)
|
||||
|
||||
func (t Tuning) String() string {
|
||||
switch t {
|
||||
case TuningAuto:
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: lib/config/tuning.proto
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
_ "github.com/gogo/protobuf/gogoproto"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
type Tuning int32
|
||||
|
||||
const (
|
||||
TuningAuto Tuning = 0
|
||||
TuningSmall Tuning = 1
|
||||
TuningLarge Tuning = 2
|
||||
)
|
||||
|
||||
var Tuning_name = map[int32]string{
|
||||
0: "TUNING_AUTO",
|
||||
1: "TUNING_SMALL",
|
||||
2: "TUNING_LARGE",
|
||||
}
|
||||
|
||||
var Tuning_value = map[string]int32{
|
||||
"TUNING_AUTO": 0,
|
||||
"TUNING_SMALL": 1,
|
||||
"TUNING_LARGE": 2,
|
||||
}
|
||||
|
||||
func (Tuning) EnumDescriptor() ([]byte, []int) {
|
||||
return fileDescriptor_204cfa1615fdfefd, []int{0}
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterEnum("config.Tuning", Tuning_name, Tuning_value)
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("lib/config/tuning.proto", fileDescriptor_204cfa1615fdfefd) }
|
||||
|
||||
var fileDescriptor_204cfa1615fdfefd = []byte{
|
||||
// 228 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xcf, 0xc9, 0x4c, 0xd2,
|
||||
0x4f, 0xce, 0xcf, 0x4b, 0xcb, 0x4c, 0xd7, 0x2f, 0x29, 0xcd, 0xcb, 0xcc, 0x4b, 0xd7, 0x2b, 0x28,
|
||||
0xca, 0x2f, 0xc9, 0x17, 0x62, 0x83, 0x08, 0x4a, 0x29, 0x17, 0xa5, 0x16, 0xe4, 0x17, 0xeb, 0x83,
|
||||
0x05, 0x93, 0x4a, 0xd3, 0xf4, 0xd3, 0xf3, 0xd3, 0xf3, 0xc1, 0x1c, 0x30, 0x0b, 0xa2, 0x58, 0xab,
|
||||
0x94, 0x8b, 0x2d, 0x04, 0xac, 0x59, 0x48, 0x9e, 0x8b, 0x3b, 0x24, 0xd4, 0xcf, 0xd3, 0xcf, 0x3d,
|
||||
0xde, 0x31, 0x34, 0xc4, 0x5f, 0x80, 0x41, 0x8a, 0xaf, 0x6b, 0xae, 0x02, 0x17, 0x44, 0xd2, 0xb1,
|
||||
0xb4, 0x24, 0x5f, 0x48, 0x91, 0x8b, 0x07, 0xaa, 0x20, 0xd8, 0xd7, 0xd1, 0xc7, 0x47, 0x80, 0x51,
|
||||
0x8a, 0xbf, 0x6b, 0xae, 0x02, 0x37, 0x44, 0x45, 0x70, 0x6e, 0x62, 0x4e, 0x0e, 0x92, 0x12, 0x1f,
|
||||
0xc7, 0x20, 0x77, 0x57, 0x01, 0x26, 0x64, 0x25, 0x3e, 0x89, 0x45, 0xe9, 0xa9, 0x52, 0x2c, 0x2b,
|
||||
0x96, 0xc8, 0x31, 0x38, 0x79, 0x9f, 0x78, 0x28, 0xc7, 0x70, 0xe1, 0xa1, 0x1c, 0xc3, 0x89, 0x47,
|
||||
0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x4e, 0x78, 0x2c, 0xc7, 0xb0, 0xe0, 0xb1, 0x1c, 0xe3, 0x85,
|
||||
0xc7, 0x72, 0x0c, 0x37, 0x1e, 0xcb, 0x31, 0x44, 0x69, 0xa6, 0x67, 0x96, 0x64, 0x94, 0x26, 0xe9,
|
||||
0x25, 0xe7, 0xe7, 0xea, 0x17, 0x57, 0xe6, 0x25, 0x97, 0x64, 0x64, 0xe6, 0xa5, 0x23, 0xb1, 0x10,
|
||||
0xbe, 0x4f, 0x62, 0x03, 0x7b, 0xc5, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0x9f, 0x69, 0xc8, 0xbc,
|
||||
0x12, 0x01, 0x00, 0x00,
|
||||
}
|
||||
@@ -11,17 +11,29 @@ import (
|
||||
"encoding/xml"
|
||||
"sort"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/fs"
|
||||
"github.com/syncthing/syncthing/lib/structutil"
|
||||
)
|
||||
|
||||
// VersioningConfiguration is used in the code and for JSON serialization
|
||||
type VersioningConfiguration struct {
|
||||
Type string `json:"type" xml:"type,attr"`
|
||||
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"`
|
||||
}
|
||||
|
||||
func (c *VersioningConfiguration) Reset() {
|
||||
*c = VersioningConfiguration{}
|
||||
}
|
||||
|
||||
// internalVersioningConfiguration is used in XML serialization
|
||||
type internalVersioningConfiguration struct {
|
||||
Type string `xml:"type,attr,omitempty"`
|
||||
Params []internalParam `xml:"param"`
|
||||
CleanupIntervalS int `xml:"cleanupIntervalS" default:"3600"`
|
||||
FSPath string `xml:"fsPath"`
|
||||
FSType fs.FilesystemType `xml:"fsType"`
|
||||
Type string `xml:"type,attr,omitempty"`
|
||||
Params []internalParam `xml:"param"`
|
||||
CleanupIntervalS int `xml:"cleanupIntervalS" default:"3600"`
|
||||
FSPath string `xml:"fsPath"`
|
||||
FSType FilesystemType `xml:"fsType"`
|
||||
}
|
||||
|
||||
type internalParam struct {
|
||||
|
||||
@@ -1,591 +0,0 @@
|
||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: lib/config/versioningconfiguration.proto
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
fs "github.com/syncthing/syncthing/lib/fs"
|
||||
_ "github.com/syncthing/syncthing/proto/ext"
|
||||
io "io"
|
||||
math "math"
|
||||
math_bits "math/bits"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
// VersioningConfiguration is used in the code and for JSON serialization
|
||||
type VersioningConfiguration struct {
|
||||
Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type" xml:"type,attr"`
|
||||
Params map[string]string `protobuf:"bytes,2,rep,name=parameters,proto3" json:"params" xml:"parameter" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
||||
CleanupIntervalS int `protobuf:"varint,3,opt,name=cleanup_interval_s,json=cleanupIntervalS,proto3,casttype=int" json:"cleanupIntervalS" xml:"cleanupIntervalS" default:"3600"`
|
||||
FSPath string `protobuf:"bytes,4,opt,name=fs_path,json=fsPath,proto3" json:"fsPath" xml:"fsPath"`
|
||||
FSType fs.FilesystemType `protobuf:"varint,5,opt,name=fs_type,json=fsType,proto3,enum=fs.FilesystemType" json:"fsType" xml:"fsType"`
|
||||
}
|
||||
|
||||
func (m *VersioningConfiguration) Reset() { *m = VersioningConfiguration{} }
|
||||
func (m *VersioningConfiguration) String() string { return proto.CompactTextString(m) }
|
||||
func (*VersioningConfiguration) ProtoMessage() {}
|
||||
func (*VersioningConfiguration) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_95ba6bdb22ffea81, []int{0}
|
||||
}
|
||||
func (m *VersioningConfiguration) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *VersioningConfiguration) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_VersioningConfiguration.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *VersioningConfiguration) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_VersioningConfiguration.Merge(m, src)
|
||||
}
|
||||
func (m *VersioningConfiguration) XXX_Size() int {
|
||||
return m.ProtoSize()
|
||||
}
|
||||
func (m *VersioningConfiguration) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_VersioningConfiguration.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_VersioningConfiguration proto.InternalMessageInfo
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*VersioningConfiguration)(nil), "config.VersioningConfiguration")
|
||||
proto.RegisterMapType((map[string]string)(nil), "config.VersioningConfiguration.ParametersEntry")
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("lib/config/versioningconfiguration.proto", fileDescriptor_95ba6bdb22ffea81)
|
||||
}
|
||||
|
||||
var fileDescriptor_95ba6bdb22ffea81 = []byte{
|
||||
// 514 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x53, 0x4f, 0x6b, 0xdb, 0x4e,
|
||||
0x10, 0x95, 0xfc, 0xef, 0x87, 0x95, 0x1f, 0x4d, 0x59, 0x0a, 0x15, 0x3e, 0x68, 0x8d, 0x70, 0x8b,
|
||||
0x0a, 0x45, 0x0e, 0x09, 0x94, 0x62, 0x0a, 0x05, 0x97, 0xa6, 0x94, 0xf6, 0x10, 0x94, 0xd0, 0x43,
|
||||
0x7b, 0x30, 0x6b, 0x77, 0x65, 0x2f, 0x91, 0x57, 0x42, 0xbb, 0x36, 0x51, 0x3f, 0x45, 0xe8, 0x27,
|
||||
0xe8, 0xc7, 0xf1, 0xcd, 0x3e, 0xf6, 0xb4, 0x10, 0xfb, 0xa6, 0xa3, 0x8e, 0xe9, 0xa5, 0xec, 0xae,
|
||||
0xa2, 0x9a, 0x94, 0xde, 0xe6, 0xcd, 0x7b, 0xf3, 0x66, 0x46, 0xb3, 0xb2, 0xbc, 0x88, 0x8c, 0xfb,
|
||||
0x93, 0x98, 0x86, 0x64, 0xda, 0x5f, 0xe2, 0x94, 0x91, 0x98, 0x12, 0x3a, 0xd5, 0x89, 0x45, 0x8a,
|
||||
0x38, 0x89, 0xa9, 0x9f, 0xa4, 0x31, 0x8f, 0x41, 0x4b, 0x27, 0x3b, 0x40, 0x56, 0x84, 0xac, 0xcf,
|
||||
0xb3, 0x04, 0x33, 0xcd, 0x75, 0xda, 0xf8, 0x8a, 0xeb, 0xd0, 0xfd, 0xd5, 0xb0, 0x1e, 0x7f, 0xaa,
|
||||
0x8c, 0xde, 0xec, 0x1b, 0x81, 0x57, 0x56, 0x43, 0x56, 0xd9, 0x66, 0xd7, 0xf4, 0xda, 0x43, 0x2f,
|
||||
0x17, 0x50, 0xe1, 0x42, 0xc0, 0xc3, 0xab, 0x79, 0x34, 0x70, 0x25, 0x78, 0x8e, 0x38, 0x4f, 0xdd,
|
||||
0x7c, 0xdd, 0x6b, 0x57, 0x28, 0x50, 0x2a, 0x70, 0x6d, 0x5a, 0x56, 0x82, 0x52, 0x34, 0xc7, 0x1c,
|
||||
0xa7, 0xcc, 0xae, 0x75, 0xeb, 0xde, 0xc1, 0x71, 0xdf, 0xd7, 0x63, 0xf9, 0xff, 0xe8, 0xe9, 0x9f,
|
||||
0x55, 0x15, 0x6f, 0x29, 0x4f, 0xb3, 0xe1, 0xeb, 0x95, 0x80, 0xc6, 0x56, 0xc0, 0x96, 0x22, 0x58,
|
||||
0x2e, 0x60, 0x4b, 0x99, 0xb2, 0x6a, 0x8a, 0xaa, 0x87, 0x5b, 0xac, 0x7b, 0x25, 0xf9, 0x7d, 0xd3,
|
||||
0x2b, 0x0b, 0x82, 0xbd, 0x19, 0xc0, 0x37, 0x0b, 0x4c, 0x22, 0x8c, 0xe8, 0x22, 0x19, 0x11, 0xca,
|
||||
0x71, 0xba, 0x44, 0xd1, 0x88, 0xd9, 0xf5, 0xae, 0xe9, 0x35, 0x87, 0x1f, 0x73, 0x01, 0x1f, 0x96,
|
||||
0xec, 0xfb, 0x92, 0x3c, 0x2f, 0x04, 0x7c, 0xa2, 0x9a, 0xdc, 0x27, 0xdc, 0xee, 0x57, 0x1c, 0xa2,
|
||||
0x45, 0xc4, 0x07, 0xee, 0xc9, 0x8b, 0xa3, 0x23, 0xf7, 0x56, 0xc0, 0x3a, 0xa1, 0xfc, 0x76, 0xdd,
|
||||
0x6b, 0x48, 0x1c, 0xfc, 0xe5, 0x04, 0xde, 0x59, 0xff, 0x85, 0x6c, 0x94, 0x20, 0x3e, 0xb3, 0x1b,
|
||||
0xea, 0x7b, 0xfa, 0x72, 0xab, 0xd3, 0xf3, 0x33, 0xc4, 0x67, 0x72, 0xab, 0x90, 0xc9, 0xa8, 0x10,
|
||||
0xf0, 0x7f, 0xd5, 0x50, 0x43, 0x57, 0x2e, 0xa2, 0x35, 0x41, 0xa9, 0x00, 0x5f, 0x94, 0x91, 0x3a,
|
||||
0x4c, 0xb3, 0x6b, 0x7a, 0x0f, 0x8e, 0x81, 0x1f, 0x32, 0xff, 0x94, 0x44, 0x98, 0x65, 0x8c, 0xe3,
|
||||
0xf9, 0x45, 0x96, 0xe0, 0x3b, 0x73, 0x19, 0x6b, 0xf3, 0x0b, 0x7d, 0xb8, 0x3b, 0x73, 0x09, 0x4b,
|
||||
0x73, 0x19, 0x06, 0xa5, 0xa2, 0x33, 0xb7, 0x0e, 0xef, 0x5d, 0x00, 0x3c, 0xb5, 0xea, 0x97, 0x38,
|
||||
0x2b, 0x1f, 0xc1, 0xa3, 0x5c, 0x40, 0x09, 0x0b, 0x01, 0xdb, 0xca, 0xea, 0x12, 0x67, 0x6e, 0x20,
|
||||
0x33, 0xc0, 0xb7, 0x9a, 0x4b, 0x14, 0x2d, 0xb0, 0x5d, 0x53, 0x4a, 0x3b, 0x17, 0x50, 0x27, 0x0a,
|
||||
0x01, 0x0f, 0x94, 0x56, 0x21, 0x37, 0xd0, 0xd9, 0x41, 0xed, 0xa5, 0x39, 0xfc, 0xb0, 0xba, 0x71,
|
||||
0x8c, 0xcd, 0x8d, 0x63, 0xac, 0xb6, 0x8e, 0xb9, 0xd9, 0x3a, 0xe6, 0xf5, 0xce, 0x31, 0x7e, 0xec,
|
||||
0x1c, 0x73, 0xb3, 0x73, 0x8c, 0x9f, 0x3b, 0xc7, 0xf8, 0xfc, 0x6c, 0x4a, 0xf8, 0x6c, 0x31, 0xf6,
|
||||
0x27, 0xf1, 0xbc, 0xcf, 0x32, 0x3a, 0xe1, 0x33, 0x42, 0xa7, 0x7b, 0xd1, 0x9f, 0xff, 0x61, 0xdc,
|
||||
0x52, 0x2f, 0xfa, 0xe4, 0x77, 0x00, 0x00, 0x00, 0xff, 0xff, 0xd1, 0x04, 0xd0, 0xd5, 0x24, 0x03,
|
||||
0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *VersioningConfiguration) Marshal() (dAtA []byte, err error) {
|
||||
size := m.ProtoSize()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *VersioningConfiguration) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.ProtoSize()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *VersioningConfiguration) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.FSType != 0 {
|
||||
i = encodeVarintVersioningconfiguration(dAtA, i, uint64(m.FSType))
|
||||
i--
|
||||
dAtA[i] = 0x28
|
||||
}
|
||||
if len(m.FSPath) > 0 {
|
||||
i -= len(m.FSPath)
|
||||
copy(dAtA[i:], m.FSPath)
|
||||
i = encodeVarintVersioningconfiguration(dAtA, i, uint64(len(m.FSPath)))
|
||||
i--
|
||||
dAtA[i] = 0x22
|
||||
}
|
||||
if m.CleanupIntervalS != 0 {
|
||||
i = encodeVarintVersioningconfiguration(dAtA, i, uint64(m.CleanupIntervalS))
|
||||
i--
|
||||
dAtA[i] = 0x18
|
||||
}
|
||||
if len(m.Params) > 0 {
|
||||
for k := range m.Params {
|
||||
v := m.Params[k]
|
||||
baseI := i
|
||||
i -= len(v)
|
||||
copy(dAtA[i:], v)
|
||||
i = encodeVarintVersioningconfiguration(dAtA, i, uint64(len(v)))
|
||||
i--
|
||||
dAtA[i] = 0x12
|
||||
i -= len(k)
|
||||
copy(dAtA[i:], k)
|
||||
i = encodeVarintVersioningconfiguration(dAtA, i, uint64(len(k)))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
i = encodeVarintVersioningconfiguration(dAtA, i, uint64(baseI-i))
|
||||
i--
|
||||
dAtA[i] = 0x12
|
||||
}
|
||||
}
|
||||
if len(m.Type) > 0 {
|
||||
i -= len(m.Type)
|
||||
copy(dAtA[i:], m.Type)
|
||||
i = encodeVarintVersioningconfiguration(dAtA, i, uint64(len(m.Type)))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func encodeVarintVersioningconfiguration(dAtA []byte, offset int, v uint64) int {
|
||||
offset -= sovVersioningconfiguration(v)
|
||||
base := offset
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return base
|
||||
}
|
||||
func (m *VersioningConfiguration) ProtoSize() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
l = len(m.Type)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovVersioningconfiguration(uint64(l))
|
||||
}
|
||||
if len(m.Params) > 0 {
|
||||
for k, v := range m.Params {
|
||||
_ = k
|
||||
_ = v
|
||||
mapEntrySize := 1 + len(k) + sovVersioningconfiguration(uint64(len(k))) + 1 + len(v) + sovVersioningconfiguration(uint64(len(v)))
|
||||
n += mapEntrySize + 1 + sovVersioningconfiguration(uint64(mapEntrySize))
|
||||
}
|
||||
}
|
||||
if m.CleanupIntervalS != 0 {
|
||||
n += 1 + sovVersioningconfiguration(uint64(m.CleanupIntervalS))
|
||||
}
|
||||
l = len(m.FSPath)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovVersioningconfiguration(uint64(l))
|
||||
}
|
||||
if m.FSType != 0 {
|
||||
n += 1 + sovVersioningconfiguration(uint64(m.FSType))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovVersioningconfiguration(x uint64) (n int) {
|
||||
return (math_bits.Len64(x|1) + 6) / 7
|
||||
}
|
||||
func sozVersioningconfiguration(x uint64) (n int) {
|
||||
return sovVersioningconfiguration(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (m *VersioningConfiguration) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowVersioningconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: VersioningConfiguration: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: VersioningConfiguration: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowVersioningconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthVersioningconfiguration
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthVersioningconfiguration
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Type = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowVersioningconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthVersioningconfiguration
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthVersioningconfiguration
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if m.Params == nil {
|
||||
m.Params = make(map[string]string)
|
||||
}
|
||||
var mapkey string
|
||||
var mapvalue string
|
||||
for iNdEx < postIndex {
|
||||
entryPreIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowVersioningconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
if fieldNum == 1 {
|
||||
var stringLenmapkey uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowVersioningconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLenmapkey |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLenmapkey := int(stringLenmapkey)
|
||||
if intStringLenmapkey < 0 {
|
||||
return ErrInvalidLengthVersioningconfiguration
|
||||
}
|
||||
postStringIndexmapkey := iNdEx + intStringLenmapkey
|
||||
if postStringIndexmapkey < 0 {
|
||||
return ErrInvalidLengthVersioningconfiguration
|
||||
}
|
||||
if postStringIndexmapkey > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
mapkey = string(dAtA[iNdEx:postStringIndexmapkey])
|
||||
iNdEx = postStringIndexmapkey
|
||||
} else if fieldNum == 2 {
|
||||
var stringLenmapvalue uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowVersioningconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLenmapvalue |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLenmapvalue := int(stringLenmapvalue)
|
||||
if intStringLenmapvalue < 0 {
|
||||
return ErrInvalidLengthVersioningconfiguration
|
||||
}
|
||||
postStringIndexmapvalue := iNdEx + intStringLenmapvalue
|
||||
if postStringIndexmapvalue < 0 {
|
||||
return ErrInvalidLengthVersioningconfiguration
|
||||
}
|
||||
if postStringIndexmapvalue > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue])
|
||||
iNdEx = postStringIndexmapvalue
|
||||
} else {
|
||||
iNdEx = entryPreIndex
|
||||
skippy, err := skipVersioningconfiguration(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthVersioningconfiguration
|
||||
}
|
||||
if (iNdEx + skippy) > postIndex {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
m.Params[mapkey] = mapvalue
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field CleanupIntervalS", wireType)
|
||||
}
|
||||
m.CleanupIntervalS = 0
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowVersioningconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.CleanupIntervalS |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 4:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field FSPath", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowVersioningconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthVersioningconfiguration
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthVersioningconfiguration
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.FSPath = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 5:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field FSType", wireType)
|
||||
}
|
||||
m.FSType = 0
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowVersioningconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.FSType |= fs.FilesystemType(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipVersioningconfiguration(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthVersioningconfiguration
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipVersioningconfiguration(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
depth := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowVersioningconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowVersioningconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if dAtA[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowVersioningconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthVersioningconfiguration
|
||||
}
|
||||
iNdEx += length
|
||||
case 3:
|
||||
depth++
|
||||
case 4:
|
||||
if depth == 0 {
|
||||
return 0, ErrUnexpectedEndOfGroupVersioningconfiguration
|
||||
}
|
||||
depth--
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
if iNdEx < 0 {
|
||||
return 0, ErrInvalidLengthVersioningconfiguration
|
||||
}
|
||||
if depth == 0 {
|
||||
return iNdEx, nil
|
||||
}
|
||||
}
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthVersioningconfiguration = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowVersioningconfiguration = fmt.Errorf("proto: integer overflow")
|
||||
ErrUnexpectedEndOfGroupVersioningconfiguration = fmt.Errorf("proto: unexpected end of group")
|
||||
)
|
||||
@@ -17,12 +17,13 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/thejerf/suture/v4"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
"github.com/syncthing/syncthing/lib/osutil"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
"github.com/syncthing/syncthing/lib/sliceutil"
|
||||
"github.com/syncthing/syncthing/lib/sync"
|
||||
"github.com/thejerf/suture/v4"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -12,10 +12,11 @@ import (
|
||||
"io"
|
||||
"sync/atomic"
|
||||
|
||||
"golang.org/x/time/rate"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
"github.com/syncthing/syncthing/lib/sync"
|
||||
"golang.org/x/time/rate"
|
||||
)
|
||||
|
||||
// limiter manages a read and write rate limit, reacting to config changes
|
||||
|
||||
@@ -15,10 +15,11 @@ import (
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/time/rate"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
"golang.org/x/time/rate"
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
@@ -28,6 +28,9 @@ import (
|
||||
stdsync "sync"
|
||||
"time"
|
||||
|
||||
"github.com/thejerf/suture/v4"
|
||||
"golang.org/x/time/rate"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/build"
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/connections/registry"
|
||||
@@ -45,9 +48,6 @@ import (
|
||||
// Registers NAT service providers
|
||||
_ "github.com/syncthing/syncthing/lib/pmp"
|
||||
_ "github.com/syncthing/syncthing/lib/upnp"
|
||||
|
||||
"github.com/thejerf/suture/v4"
|
||||
"golang.org/x/time/rate"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -445,7 +445,7 @@ func (s *service) handleHellos(ctx context.Context) error {
|
||||
// connections are limited.
|
||||
rd, wr := s.limiter.getLimiters(remoteID, c, c.IsLocal())
|
||||
|
||||
protoConn := protocol.NewConnection(remoteID, rd, wr, c, s.model, c, deviceCfg.Compression, s.cfg.FolderPasswords(remoteID), s.keyGen)
|
||||
protoConn := protocol.NewConnection(remoteID, rd, wr, c, s.model, c, deviceCfg.Compression.ToProtocol(), s.cfg.FolderPasswords(remoteID), s.keyGen)
|
||||
s.accountAddedConnection(protoConn, hello, s.cfg.Options().ConnectionPriorityUpgradeThreshold)
|
||||
go func() {
|
||||
<-protoConn.Closed()
|
||||
@@ -1284,6 +1284,7 @@ func (r nextDialRegistry) redialDevice(device protocol.DeviceID, now time.Time)
|
||||
}
|
||||
dev.attempts++
|
||||
dev.nextDial = make(map[string]time.Time)
|
||||
r[device] = dev
|
||||
return
|
||||
}
|
||||
if dev.attempts >= dialCoolDownMaxAttempts && now.Before(dev.coolDownIntervalStart.Add(dialCoolDownDelay)) {
|
||||
|
||||
@@ -15,14 +15,14 @@ import (
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/thejerf/suture/v4"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/connections/registry"
|
||||
"github.com/syncthing/syncthing/lib/nat"
|
||||
"github.com/syncthing/syncthing/lib/osutil"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
"github.com/syncthing/syncthing/lib/stats"
|
||||
|
||||
"github.com/thejerf/suture/v4"
|
||||
)
|
||||
|
||||
type tlsConn interface {
|
||||
|
||||
@@ -185,7 +185,7 @@ func BenchmarkNeedHalf(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
count := 0
|
||||
snap := snapshot(b, benchS)
|
||||
snap.WithNeed(protocol.LocalDeviceID, func(fi protocol.FileIntf) bool {
|
||||
snap.WithNeed(protocol.LocalDeviceID, func(fi protocol.FileInfo) bool {
|
||||
count++
|
||||
return true
|
||||
})
|
||||
@@ -209,7 +209,7 @@ func BenchmarkNeedHalfRemote(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
count := 0
|
||||
snap := snapshot(b, fset)
|
||||
snap.WithNeed(remoteDevice0, func(fi protocol.FileIntf) bool {
|
||||
snap.WithNeed(remoteDevice0, func(fi protocol.FileInfo) bool {
|
||||
count++
|
||||
return true
|
||||
})
|
||||
@@ -230,7 +230,7 @@ func BenchmarkHave(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
count := 0
|
||||
snap := snapshot(b, benchS)
|
||||
snap.WithHave(protocol.LocalDeviceID, func(fi protocol.FileIntf) bool {
|
||||
snap.WithHave(protocol.LocalDeviceID, func(fi protocol.FileInfo) bool {
|
||||
count++
|
||||
return true
|
||||
})
|
||||
@@ -251,7 +251,7 @@ func BenchmarkGlobal(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
count := 0
|
||||
snap := snapshot(b, benchS)
|
||||
snap.WithGlobal(func(fi protocol.FileIntf) bool {
|
||||
snap.WithGlobal(func(fi protocol.FileInfo) bool {
|
||||
count++
|
||||
return true
|
||||
})
|
||||
@@ -272,7 +272,7 @@ func BenchmarkNeedHalfTruncated(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
count := 0
|
||||
snap := snapshot(b, benchS)
|
||||
snap.WithNeedTruncated(protocol.LocalDeviceID, func(fi protocol.FileIntf) bool {
|
||||
snap.WithNeedTruncated(protocol.LocalDeviceID, func(fi protocol.FileInfo) bool {
|
||||
count++
|
||||
return true
|
||||
})
|
||||
@@ -293,7 +293,7 @@ func BenchmarkHaveTruncated(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
count := 0
|
||||
snap := snapshot(b, benchS)
|
||||
snap.WithHaveTruncated(protocol.LocalDeviceID, func(fi protocol.FileIntf) bool {
|
||||
snap.WithHaveTruncated(protocol.LocalDeviceID, func(fi protocol.FileInfo) bool {
|
||||
count++
|
||||
return true
|
||||
})
|
||||
@@ -314,7 +314,7 @@ func BenchmarkGlobalTruncated(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
count := 0
|
||||
snap := snapshot(b, benchS)
|
||||
snap.WithGlobalTruncated(func(fi protocol.FileIntf) bool {
|
||||
snap.WithGlobalTruncated(func(fi protocol.FileInfo) bool {
|
||||
count++
|
||||
return true
|
||||
})
|
||||
|
||||
+7
-316
@@ -30,107 +30,10 @@ func genBlocks(n int) []protocol.BlockInfo {
|
||||
return b
|
||||
}
|
||||
|
||||
func TestIgnoredFiles(t *testing.T) {
|
||||
ldb, err := openJSONS("testdata/v0.14.48-ignoredfiles.db.jsons")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
db := newLowlevel(t, ldb)
|
||||
defer db.Close()
|
||||
if err := UpdateSchema(db); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
fs := newFileSet(t, "test", db)
|
||||
|
||||
// The contents of the database are like this:
|
||||
//
|
||||
// fs := newFileSet(t, "test", db)
|
||||
// fs.Update(protocol.LocalDeviceID, []protocol.FileInfo{
|
||||
// { // invalid (ignored) file
|
||||
// Name: "foo",
|
||||
// Type: protocol.FileInfoTypeFile,
|
||||
// Invalid: true,
|
||||
// Version: protocol.Vector{Counters: []protocol.Counter{{ID: 1, Value: 1000}}},
|
||||
// },
|
||||
// { // regular file
|
||||
// Name: "bar",
|
||||
// Type: protocol.FileInfoTypeFile,
|
||||
// Version: protocol.Vector{Counters: []protocol.Counter{{ID: 1, Value: 1001}}},
|
||||
// },
|
||||
// })
|
||||
// fs.Update(protocol.DeviceID{42}, []protocol.FileInfo{
|
||||
// { // invalid file
|
||||
// Name: "baz",
|
||||
// Type: protocol.FileInfoTypeFile,
|
||||
// Invalid: true,
|
||||
// Version: protocol.Vector{Counters: []protocol.Counter{{ID: 42, Value: 1000}}},
|
||||
// },
|
||||
// { // regular file
|
||||
// Name: "quux",
|
||||
// Type: protocol.FileInfoTypeFile,
|
||||
// Version: protocol.Vector{Counters: []protocol.Counter{{ID: 42, Value: 1002}}},
|
||||
// },
|
||||
// })
|
||||
|
||||
// Local files should have the "ignored" bit in addition to just being
|
||||
// generally invalid if we want to look at the simulation of that bit.
|
||||
|
||||
snap := snapshot(t, fs)
|
||||
defer snap.Release()
|
||||
fi, ok := snap.Get(protocol.LocalDeviceID, "foo")
|
||||
if !ok {
|
||||
t.Fatal("foo should exist")
|
||||
}
|
||||
if !fi.IsInvalid() {
|
||||
t.Error("foo should be invalid")
|
||||
}
|
||||
if !fi.IsIgnored() {
|
||||
t.Error("foo should be ignored")
|
||||
}
|
||||
|
||||
fi, ok = snap.Get(protocol.LocalDeviceID, "bar")
|
||||
if !ok {
|
||||
t.Fatal("bar should exist")
|
||||
}
|
||||
if fi.IsInvalid() {
|
||||
t.Error("bar should not be invalid")
|
||||
}
|
||||
if fi.IsIgnored() {
|
||||
t.Error("bar should not be ignored")
|
||||
}
|
||||
|
||||
// Remote files have the invalid bit as usual, and the IsInvalid() method
|
||||
// should pick this up too.
|
||||
|
||||
fi, ok = snap.Get(protocol.DeviceID{42}, "baz")
|
||||
if !ok {
|
||||
t.Fatal("baz should exist")
|
||||
}
|
||||
if !fi.IsInvalid() {
|
||||
t.Error("baz should be invalid")
|
||||
}
|
||||
if !fi.IsInvalid() {
|
||||
t.Error("baz should be invalid")
|
||||
}
|
||||
|
||||
fi, ok = snap.Get(protocol.DeviceID{42}, "quux")
|
||||
if !ok {
|
||||
t.Fatal("quux should exist")
|
||||
}
|
||||
if fi.IsInvalid() {
|
||||
t.Error("quux should not be invalid")
|
||||
}
|
||||
if fi.IsInvalid() {
|
||||
t.Error("quux should not be invalid")
|
||||
}
|
||||
}
|
||||
|
||||
const myID = 1
|
||||
|
||||
var (
|
||||
remoteDevice0, remoteDevice1 protocol.DeviceID
|
||||
update0to3Folder = "UpdateSchema0to3"
|
||||
invalid = "invalid"
|
||||
slashPrefixed = "/notgood"
|
||||
haveUpdate0to3 map[protocol.DeviceID][]protocol.FileInfo
|
||||
@@ -157,142 +60,6 @@ func init() {
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdate0to3(t *testing.T) {
|
||||
ldb, err := openJSONS("testdata/v0.14.45-update0to3.db.jsons")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
db := newLowlevel(t, ldb)
|
||||
defer db.Close()
|
||||
updater := schemaUpdater{db}
|
||||
|
||||
folder := []byte(update0to3Folder)
|
||||
|
||||
if err := updater.updateSchema0to1(0); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
trans, err := db.newReadOnlyTransaction()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer trans.Release()
|
||||
if _, ok, err := trans.getFile(folder, protocol.LocalDeviceID[:], []byte(slashPrefixed)); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if ok {
|
||||
t.Error("File prefixed by '/' was not removed during transition to schema 1")
|
||||
}
|
||||
|
||||
var key []byte
|
||||
|
||||
key, err = db.keyer.GenerateGlobalVersionKey(nil, folder, []byte(invalid))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := db.Get(key); err != nil {
|
||||
t.Error("Invalid file wasn't added to global list")
|
||||
}
|
||||
|
||||
if err := updater.updateSchema1to2(1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
found := false
|
||||
trans, err = db.newReadOnlyTransaction()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer trans.Release()
|
||||
_ = trans.withHaveSequence(folder, 0, func(fi protocol.FileIntf) bool {
|
||||
f := fi.(protocol.FileInfo)
|
||||
l.Infoln(f)
|
||||
if found {
|
||||
t.Error("Unexpected additional file via sequence", f.FileName())
|
||||
return true
|
||||
}
|
||||
if e := haveUpdate0to3[protocol.LocalDeviceID][0]; f.IsEquivalentOptional(e, protocol.FileInfoComparison{IgnorePerms: true, IgnoreBlocks: true}) {
|
||||
found = true
|
||||
} else {
|
||||
t.Errorf("Wrong file via sequence, got %v, expected %v", f, e)
|
||||
}
|
||||
return true
|
||||
})
|
||||
if !found {
|
||||
t.Error("Local file wasn't added to sequence bucket", err)
|
||||
}
|
||||
|
||||
if err := updater.updateSchema2to3(2); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
need := map[string]protocol.FileInfo{
|
||||
haveUpdate0to3[remoteDevice0][0].Name: haveUpdate0to3[remoteDevice0][0],
|
||||
haveUpdate0to3[remoteDevice1][0].Name: haveUpdate0to3[remoteDevice1][0],
|
||||
haveUpdate0to3[remoteDevice0][2].Name: haveUpdate0to3[remoteDevice0][2],
|
||||
}
|
||||
|
||||
trans, err = db.newReadOnlyTransaction()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer trans.Release()
|
||||
|
||||
key, err = trans.keyer.GenerateNeedFileKey(nil, folder, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
dbi, err := trans.NewPrefixIterator(key)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer dbi.Release()
|
||||
|
||||
for dbi.Next() {
|
||||
name := trans.keyer.NameFromGlobalVersionKey(dbi.Key())
|
||||
key, err = trans.keyer.GenerateGlobalVersionKey(key, folder, name)
|
||||
bs, err := trans.Get(key)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var vl VersionListDeprecated
|
||||
if err := vl.Unmarshal(bs); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
key, err = trans.keyer.GenerateDeviceFileKey(key, folder, vl.Versions[0].Device, name)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
fi, ok, err := trans.getFileTrunc(key, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !ok {
|
||||
device := "<invalid>"
|
||||
if dev, err := protocol.DeviceIDFromBytes(vl.Versions[0].Device); err != nil {
|
||||
device = dev.String()
|
||||
}
|
||||
t.Fatal("surprise missing global file", string(name), device)
|
||||
}
|
||||
e, ok := need[fi.FileName()]
|
||||
if !ok {
|
||||
t.Error("Got unexpected needed file:", fi.FileName())
|
||||
}
|
||||
f := fi.(protocol.FileInfo)
|
||||
delete(need, f.Name)
|
||||
if !f.IsEquivalentOptional(e, protocol.FileInfoComparison{IgnorePerms: true, IgnoreBlocks: true}) {
|
||||
t.Errorf("Wrong needed file, got %v, expected %v", f, e)
|
||||
}
|
||||
}
|
||||
if dbi.Error() != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for n := range need {
|
||||
t.Errorf(`Missing needed file "%v"`, n)
|
||||
}
|
||||
}
|
||||
|
||||
// TestRepairSequence checks that a few hand-crafted messed-up sequence entries get fixed.
|
||||
func TestRepairSequence(t *testing.T) {
|
||||
db := newLowlevelMemory(t)
|
||||
@@ -446,11 +213,10 @@ func TestRepairSequence(t *testing.T) {
|
||||
}
|
||||
defer it.Release()
|
||||
for it.Next() {
|
||||
intf, ok, err := ro.getFileTrunc(it.Value(), false)
|
||||
fi, ok, err := ro.getFileTrunc(it.Value(), false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
fi := intf.(protocol.FileInfo)
|
||||
seq := ro.keyer.SequenceFromSequenceKey(it.Key())
|
||||
if !ok {
|
||||
t.Errorf("Sequence entry %v points at nothing", seq)
|
||||
@@ -531,81 +297,6 @@ func TestCheckGlobals(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateTo10(t *testing.T) {
|
||||
ldb, err := openJSONS("./testdata/v1.4.0-updateTo10.json")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
db := newLowlevel(t, ldb)
|
||||
defer db.Close()
|
||||
|
||||
UpdateSchema(db)
|
||||
|
||||
folder := "test"
|
||||
|
||||
meta, err := db.getMetaAndCheck(folder)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
empty := Counts{}
|
||||
|
||||
c := meta.Counts(protocol.LocalDeviceID, needFlag)
|
||||
if c.Files != 1 {
|
||||
t.Error("Expected 1 needed file locally, got", c.Files)
|
||||
}
|
||||
c.Files = 0
|
||||
if c.Deleted != 1 {
|
||||
t.Error("Expected 1 needed deletion locally, got", c.Deleted)
|
||||
}
|
||||
c.Deleted = 0
|
||||
if !c.Equal(empty) {
|
||||
t.Error("Expected all counts to be zero, got", c)
|
||||
}
|
||||
c = meta.Counts(remoteDevice0, needFlag)
|
||||
if !c.Equal(empty) {
|
||||
t.Error("Expected all counts to be zero, got", c)
|
||||
}
|
||||
|
||||
trans, err := db.newReadOnlyTransaction()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer trans.Release()
|
||||
// a
|
||||
vl, err := trans.getGlobalVersions(nil, []byte(folder), []byte("a"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, v := range vl.RawVersions {
|
||||
if !v.Deleted {
|
||||
t.Error("Unexpected undeleted global version for a")
|
||||
}
|
||||
}
|
||||
// b
|
||||
vl, err = trans.getGlobalVersions(nil, []byte(folder), []byte("b"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !vl.RawVersions[0].Deleted {
|
||||
t.Error("vl.Versions[0] not deleted for b")
|
||||
}
|
||||
if vl.RawVersions[1].Deleted {
|
||||
t.Error("vl.Versions[1] deleted for b")
|
||||
}
|
||||
// c
|
||||
vl, err = trans.getGlobalVersions(nil, []byte(folder), []byte("c"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if vl.RawVersions[0].Deleted {
|
||||
t.Error("vl.Versions[0] deleted for c")
|
||||
}
|
||||
if !vl.RawVersions[1].Deleted {
|
||||
t.Error("vl.Versions[1] not deleted for c")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDropDuplicates(t *testing.T) {
|
||||
names := []string{
|
||||
"foo",
|
||||
@@ -769,7 +460,7 @@ func TestUpdateTo14(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
fiBs := mustMarshal(&fileWOBlocks)
|
||||
fiBs := mustMarshal(fileWOBlocks.ToWire(true))
|
||||
if err := trans.Put(key, fiBs); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -799,9 +490,9 @@ func TestUpdateTo14(t *testing.T) {
|
||||
|
||||
if vl, err := ro.getGlobalVersions(nil, folder, name); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if fv, ok := vl.GetGlobal(); !ok {
|
||||
} else if fv, ok := vlGetGlobal(vl); !ok {
|
||||
t.Error("missing global")
|
||||
} else if !fv.IsInvalid() {
|
||||
} else if !fvIsInvalid(fv) {
|
||||
t.Error("global not marked as invalid")
|
||||
}
|
||||
}
|
||||
@@ -874,8 +565,8 @@ func TestCheckLocalNeed(t *testing.T) {
|
||||
t.Errorf("Expected 2 needed files locally, got %v in meta", c.Files)
|
||||
}
|
||||
needed := make([]protocol.FileInfo, 0, 2)
|
||||
snap.WithNeed(protocol.LocalDeviceID, func(fi protocol.FileIntf) bool {
|
||||
needed = append(needed, fi.(protocol.FileInfo))
|
||||
snap.WithNeed(protocol.LocalDeviceID, func(fi protocol.FileInfo) bool {
|
||||
needed = append(needed, fi)
|
||||
return true
|
||||
})
|
||||
if l := len(needed); l != 2 {
|
||||
@@ -939,7 +630,7 @@ func TestDuplicateNeedCount(t *testing.T) {
|
||||
fs = newFileSet(t, folder, db)
|
||||
found := false
|
||||
for _, c := range fs.meta.counts.Counts {
|
||||
if bytes.Equal(protocol.LocalDeviceID[:], c.DeviceID) && c.LocalFlags == needFlag {
|
||||
if protocol.LocalDeviceID == c.DeviceID && c.LocalFlags == needFlag {
|
||||
if found {
|
||||
t.Fatal("second need count for local device encountered")
|
||||
}
|
||||
|
||||
+36
-32
@@ -19,6 +19,10 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/greatroar/blobloom"
|
||||
"github.com/thejerf/suture/v4"
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
"github.com/syncthing/syncthing/internal/gen/dbproto"
|
||||
"github.com/syncthing/syncthing/lib/db/backend"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
"github.com/syncthing/syncthing/lib/fs"
|
||||
@@ -26,7 +30,6 @@ import (
|
||||
"github.com/syncthing/syncthing/lib/stringutil"
|
||||
"github.com/syncthing/syncthing/lib/svcutil"
|
||||
"github.com/syncthing/syncthing/lib/sync"
|
||||
"github.com/thejerf/suture/v4"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -521,8 +524,8 @@ func (db *Lowlevel) checkGlobals(folderStr string) (int, error) {
|
||||
var dk []byte
|
||||
ro := t.readOnlyTransaction
|
||||
for dbi.Next() {
|
||||
var vl VersionList
|
||||
if err := vl.Unmarshal(dbi.Value()); err != nil || vl.Empty() {
|
||||
var vl dbproto.VersionList
|
||||
if err := proto.Unmarshal(dbi.Value(), &vl); err != nil || len(vl.Versions) == 0 {
|
||||
if err := t.Delete(dbi.Key()); err != nil && !backend.IsNotFound(err) {
|
||||
return 0, err
|
||||
}
|
||||
@@ -535,9 +538,9 @@ func (db *Lowlevel) checkGlobals(folderStr string) (int, error) {
|
||||
// we find those and clear them out.
|
||||
|
||||
name := db.keyer.NameFromGlobalVersionKey(dbi.Key())
|
||||
newVL := &VersionList{}
|
||||
newVL := &dbproto.VersionList{}
|
||||
var changed, changedHere bool
|
||||
for _, fv := range vl.RawVersions {
|
||||
for _, fv := range vl.Versions {
|
||||
changedHere, err = checkGlobalsFilterDevices(dk, folder, name, fv.Devices, newVL, ro)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@@ -551,7 +554,7 @@ func (db *Lowlevel) checkGlobals(folderStr string) (int, error) {
|
||||
changed = changed || changedHere
|
||||
}
|
||||
|
||||
if newVL.Empty() {
|
||||
if len(newVL.Versions) == 0 {
|
||||
if err := t.Delete(dbi.Key()); err != nil && !backend.IsNotFound(err) {
|
||||
return 0, err
|
||||
}
|
||||
@@ -572,7 +575,7 @@ func (db *Lowlevel) checkGlobals(folderStr string) (int, error) {
|
||||
return fixed, t.Commit()
|
||||
}
|
||||
|
||||
func checkGlobalsFilterDevices(dk, folder, name []byte, devices [][]byte, vl *VersionList, t readOnlyTransaction) (bool, error) {
|
||||
func checkGlobalsFilterDevices(dk, folder, name []byte, devices [][]byte, vl *dbproto.VersionList, t readOnlyTransaction) (bool, error) {
|
||||
var changed bool
|
||||
var err error
|
||||
for _, device := range devices {
|
||||
@@ -588,7 +591,7 @@ func checkGlobalsFilterDevices(dk, folder, name []byte, devices [][]byte, vl *Ve
|
||||
changed = true
|
||||
continue
|
||||
}
|
||||
_, _, _, _, _, _, err = vl.update(folder, device, f, t)
|
||||
_, _, _, _, _, _, err = vlUpdate(vl, folder, device, f, t)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -610,7 +613,7 @@ func (db *Lowlevel) getIndexID(device, folder []byte) (protocol.IndexID, error)
|
||||
|
||||
var id protocol.IndexID
|
||||
if err := id.Unmarshal(cur); err != nil {
|
||||
return 0, nil
|
||||
return 0, nil //nolint: nilerr
|
||||
}
|
||||
|
||||
return id, nil
|
||||
@@ -816,11 +819,11 @@ func (db *Lowlevel) gcIndirect(ctx context.Context) (err error) {
|
||||
default:
|
||||
}
|
||||
|
||||
var hashes IndirectionHashesOnly
|
||||
if err := hashes.Unmarshal(it.Value()); err != nil {
|
||||
var hashes dbproto.IndirectionHashesOnly
|
||||
if err := proto.Unmarshal(it.Value(), &hashes); err != nil {
|
||||
return err
|
||||
}
|
||||
db.recordIndirectionHashes(hashes)
|
||||
db.recordIndirectionHashes(&hashes)
|
||||
}
|
||||
it.Release()
|
||||
if err := it.Error(); err != nil {
|
||||
@@ -924,10 +927,10 @@ func (db *Lowlevel) gcIndirect(ctx context.Context) (err error) {
|
||||
}
|
||||
|
||||
func (db *Lowlevel) recordIndirectionHashesForFile(f *protocol.FileInfo) {
|
||||
db.recordIndirectionHashes(IndirectionHashesOnly{BlocksHash: f.BlocksHash, VersionHash: f.VersionHash})
|
||||
db.recordIndirectionHashes(&dbproto.IndirectionHashesOnly{BlocksHash: f.BlocksHash, VersionHash: f.VersionHash})
|
||||
}
|
||||
|
||||
func (db *Lowlevel) recordIndirectionHashes(hs IndirectionHashesOnly) {
|
||||
func (db *Lowlevel) recordIndirectionHashes(hs *dbproto.IndirectionHashesOnly) {
|
||||
// must be called with gcMut held (at least read-held)
|
||||
if db.blockFilter != nil && len(hs.BlocksHash) > 0 {
|
||||
db.blockFilter.add(hs.BlocksHash)
|
||||
@@ -966,7 +969,7 @@ func (b *bloomFilter) hash(id []byte) uint64 {
|
||||
}
|
||||
var h maphash.Hash
|
||||
h.SetSeed(b.seed)
|
||||
h.Write(id)
|
||||
_, _ = h.Write(id)
|
||||
return h.Sum64()
|
||||
}
|
||||
|
||||
@@ -1035,7 +1038,7 @@ func (db *Lowlevel) getMetaAndCheckGCLocked(folder string) (*metadataTracker, er
|
||||
func (db *Lowlevel) loadMetadataTracker(folder string) (*metadataTracker, error) {
|
||||
meta := newMetadataTracker(db.keyer, db.evLogger)
|
||||
if err := meta.fromDB(db, []byte(folder)); err != nil {
|
||||
if err == errMetaInconsistent {
|
||||
if errors.Is(err, errMetaInconsistent) {
|
||||
l.Infof("Stored folder metadata for %q is inconsistent; recalculating", folder)
|
||||
} else {
|
||||
l.Infof("No stored folder metadata for %q; recalculating", folder)
|
||||
@@ -1071,7 +1074,7 @@ func (db *Lowlevel) recalcMeta(folderStr string) (*metadataTracker, error) {
|
||||
defer t.close()
|
||||
|
||||
var deviceID protocol.DeviceID
|
||||
err = t.withAllFolderTruncated(folder, func(device []byte, f FileInfoTruncated) bool {
|
||||
err = t.withAllFolderTruncated(folder, func(device []byte, f protocol.FileInfo) bool {
|
||||
copy(deviceID[:], device)
|
||||
meta.addFile(deviceID, f)
|
||||
return true
|
||||
@@ -1080,7 +1083,7 @@ func (db *Lowlevel) recalcMeta(folderStr string) (*metadataTracker, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = t.withGlobal(folder, nil, true, func(f protocol.FileIntf) bool {
|
||||
err = t.withGlobal(folder, nil, true, func(f protocol.FileInfo) bool {
|
||||
meta.addFile(protocol.GlobalDeviceID, f)
|
||||
return true
|
||||
})
|
||||
@@ -1089,7 +1092,7 @@ func (db *Lowlevel) recalcMeta(folderStr string) (*metadataTracker, error) {
|
||||
}
|
||||
|
||||
meta.emptyNeeded(protocol.LocalDeviceID)
|
||||
err = t.withNeed(folder, protocol.LocalDeviceID[:], true, func(f protocol.FileIntf) bool {
|
||||
err = t.withNeed(folder, protocol.LocalDeviceID[:], true, func(f protocol.FileInfo) bool {
|
||||
meta.addNeeded(protocol.LocalDeviceID, f)
|
||||
return true
|
||||
})
|
||||
@@ -1098,7 +1101,7 @@ func (db *Lowlevel) recalcMeta(folderStr string) (*metadataTracker, error) {
|
||||
}
|
||||
for _, device := range meta.devices() {
|
||||
meta.emptyNeeded(device)
|
||||
err = t.withNeed(folder, device[:], true, func(f protocol.FileIntf) bool {
|
||||
err = t.withNeed(folder, device[:], true, func(f protocol.FileInfo) bool {
|
||||
meta.addNeeded(device, f)
|
||||
return true
|
||||
})
|
||||
@@ -1132,7 +1135,7 @@ func (db *Lowlevel) verifyLocalSequence(curSeq int64, folder string) (bool, erro
|
||||
return false, err
|
||||
}
|
||||
ok := true
|
||||
if err := t.withHaveSequence([]byte(folder), curSeq+1, func(fi protocol.FileIntf) bool {
|
||||
if err := t.withHaveSequence([]byte(folder), curSeq+1, func(_ protocol.FileInfo) bool {
|
||||
ok = false // we got something, which we should not have
|
||||
return false
|
||||
}); err != nil {
|
||||
@@ -1204,8 +1207,7 @@ func (db *Lowlevel) repairSequenceGCLocked(folderStr string, meta *metadataTrack
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
fi := intf.(protocol.FileInfo)
|
||||
if sk, err = t.keyer.GenerateSequenceKey(sk, folder, fi.Sequence); err != nil {
|
||||
if sk, err = t.keyer.GenerateSequenceKey(sk, folder, intf.Sequence); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
switch dk, err = t.Get(sk); {
|
||||
@@ -1216,14 +1218,14 @@ func (db *Lowlevel) repairSequenceGCLocked(folderStr string, meta *metadataTrack
|
||||
fallthrough
|
||||
case !bytes.Equal(it.Key(), dk):
|
||||
fixed++
|
||||
fi.Sequence = meta.nextLocalSeq()
|
||||
if sk, err = t.keyer.GenerateSequenceKey(sk, folder, fi.Sequence); err != nil {
|
||||
intf.Sequence = meta.nextLocalSeq()
|
||||
if sk, err = t.keyer.GenerateSequenceKey(sk, folder, intf.Sequence); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if err := t.Put(sk, it.Key()); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if err := t.putFile(it.Key(), fi); err != nil {
|
||||
if err := t.putFile(it.Key(), intf); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
@@ -1307,9 +1309,8 @@ func (db *Lowlevel) checkLocalNeed(folder []byte) (int, error) {
|
||||
}
|
||||
}
|
||||
next()
|
||||
t.withNeedIteratingGlobal(folder, protocol.LocalDeviceID[:], true, func(fi protocol.FileIntf) bool {
|
||||
f := fi.(FileInfoTruncated)
|
||||
for !needDone && needName < f.Name {
|
||||
itErr := t.withNeedIteratingGlobal(folder, protocol.LocalDeviceID[:], true, func(fi protocol.FileInfo) bool {
|
||||
for !needDone && needName < fi.Name {
|
||||
repaired++
|
||||
if err = t.Delete(dbi.Key()); err != nil && !backend.IsNotFound(err) {
|
||||
return false
|
||||
@@ -1317,24 +1318,27 @@ func (db *Lowlevel) checkLocalNeed(folder []byte) (int, error) {
|
||||
l.Debugln("check local need: removing", needName)
|
||||
next()
|
||||
}
|
||||
if needName == f.Name {
|
||||
if needName == fi.Name {
|
||||
next()
|
||||
} else {
|
||||
repaired++
|
||||
key, err = t.keyer.GenerateNeedFileKey(key, folder, []byte(f.Name))
|
||||
key, err = t.keyer.GenerateNeedFileKey(key, folder, []byte(fi.Name))
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
if err = t.Put(key, nil); err != nil {
|
||||
return false
|
||||
}
|
||||
l.Debugln("check local need: adding", f.Name)
|
||||
l.Debugln("check local need: adding", fi.Name)
|
||||
}
|
||||
return true
|
||||
})
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if itErr != nil {
|
||||
return 0, itErr
|
||||
}
|
||||
|
||||
for !needDone {
|
||||
repaired++
|
||||
|
||||
+36
-28
@@ -7,12 +7,14 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/bits"
|
||||
"time"
|
||||
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
"github.com/syncthing/syncthing/internal/gen/dbproto"
|
||||
"github.com/syncthing/syncthing/lib/db/backend"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
@@ -56,24 +58,34 @@ func newMetadataTracker(keyer keyer, evLogger events.Logger) *metadataTracker {
|
||||
// Unmarshal loads a metadataTracker from the corresponding protobuf
|
||||
// representation
|
||||
func (m *metadataTracker) Unmarshal(bs []byte) error {
|
||||
if err := m.counts.Unmarshal(bs); err != nil {
|
||||
var dbc dbproto.CountsSet
|
||||
if err := proto.Unmarshal(bs, &dbc); err != nil {
|
||||
return err
|
||||
}
|
||||
m.counts.Created = dbc.Created
|
||||
m.counts.Counts = make([]Counts, len(dbc.Counts))
|
||||
for i, c := range dbc.Counts {
|
||||
m.counts.Counts[i] = countsFromWire(c)
|
||||
}
|
||||
|
||||
// Initialize the index map
|
||||
m.indexes = make(map[metaKey]int)
|
||||
for i, c := range m.counts.Counts {
|
||||
dev, err := protocol.DeviceIDFromBytes(c.DeviceID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m.indexes[metaKey{dev, c.LocalFlags}] = i
|
||||
m.indexes[metaKey{c.DeviceID, c.LocalFlags}] = i
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Marshal returns the protobuf representation of the metadataTracker
|
||||
func (m *metadataTracker) Marshal() ([]byte, error) {
|
||||
return m.counts.Marshal()
|
||||
dbc := &dbproto.CountsSet{
|
||||
Counts: make([]*dbproto.Counts, len(m.counts.Counts)),
|
||||
Created: m.Created().UnixNano(),
|
||||
}
|
||||
for i, c := range m.counts.Counts {
|
||||
dbc.Counts[i] = c.toWire()
|
||||
}
|
||||
return proto.Marshal(dbc)
|
||||
}
|
||||
|
||||
func (m *metadataTracker) CommitHook(folder []byte) backend.CommitHook {
|
||||
@@ -142,7 +154,7 @@ func (m *metadataTracker) countsPtr(dev protocol.DeviceID, flag uint32) *Counts
|
||||
idx, ok := m.indexes[key]
|
||||
if !ok {
|
||||
idx = len(m.counts.Counts)
|
||||
m.counts.Counts = append(m.counts.Counts, Counts{DeviceID: dev[:], LocalFlags: flag})
|
||||
m.counts.Counts = append(m.counts.Counts, Counts{DeviceID: dev, LocalFlags: flag})
|
||||
m.indexes[key] = idx
|
||||
// Need bucket must be initialized when a device first occurs in
|
||||
// the metadatatracker, even if there's no change to the need
|
||||
@@ -160,19 +172,19 @@ func (m *metadataTracker) countsPtr(dev protocol.DeviceID, flag uint32) *Counts
|
||||
|
||||
// allNeeded makes sure there is a counts in case the device needs everything.
|
||||
func (m *countsMap) allNeededCounts(dev protocol.DeviceID) Counts {
|
||||
counts := Counts{}
|
||||
var counts Counts
|
||||
if idx, ok := m.indexes[metaKey{protocol.GlobalDeviceID, 0}]; ok {
|
||||
counts = m.counts.Counts[idx]
|
||||
counts.Deleted = 0 // Don't need deletes if having nothing
|
||||
}
|
||||
counts.DeviceID = dev[:]
|
||||
counts.DeviceID = dev
|
||||
counts.LocalFlags = needFlag
|
||||
return counts
|
||||
}
|
||||
|
||||
// addFile adds a file to the counts, adjusting the sequence number as
|
||||
// appropriate
|
||||
func (m *metadataTracker) addFile(dev protocol.DeviceID, f protocol.FileIntf) {
|
||||
func (m *metadataTracker) addFile(dev protocol.DeviceID, f protocol.FileInfo) {
|
||||
m.mut.Lock()
|
||||
defer m.mut.Unlock()
|
||||
|
||||
@@ -181,7 +193,7 @@ func (m *metadataTracker) addFile(dev protocol.DeviceID, f protocol.FileIntf) {
|
||||
m.updateFileLocked(dev, f, m.addFileLocked)
|
||||
}
|
||||
|
||||
func (m *metadataTracker) updateFileLocked(dev protocol.DeviceID, f protocol.FileIntf, fn func(protocol.DeviceID, uint32, protocol.FileIntf)) {
|
||||
func (m *metadataTracker) updateFileLocked(dev protocol.DeviceID, f protocol.FileInfo, fn func(protocol.DeviceID, uint32, protocol.FileInfo)) {
|
||||
m.dirty = true
|
||||
|
||||
if f.IsInvalid() && (f.FileLocalFlags() == 0 || dev == protocol.GlobalDeviceID) {
|
||||
@@ -209,7 +221,7 @@ func (m *metadataTracker) emptyNeeded(dev protocol.DeviceID) {
|
||||
m.dirty = true
|
||||
|
||||
empty := Counts{
|
||||
DeviceID: dev[:],
|
||||
DeviceID: dev,
|
||||
LocalFlags: needFlag,
|
||||
}
|
||||
key := metaKey{dev, needFlag}
|
||||
@@ -222,7 +234,7 @@ func (m *metadataTracker) emptyNeeded(dev protocol.DeviceID) {
|
||||
}
|
||||
|
||||
// addNeeded adds a file to the needed counts
|
||||
func (m *metadataTracker) addNeeded(dev protocol.DeviceID, f protocol.FileIntf) {
|
||||
func (m *metadataTracker) addNeeded(dev protocol.DeviceID, f protocol.FileInfo) {
|
||||
m.mut.Lock()
|
||||
defer m.mut.Unlock()
|
||||
|
||||
@@ -237,7 +249,7 @@ func (m *metadataTracker) Sequence(dev protocol.DeviceID) int64 {
|
||||
return m.countsPtr(dev, 0).Sequence
|
||||
}
|
||||
|
||||
func (m *metadataTracker) updateSeqLocked(dev protocol.DeviceID, f protocol.FileIntf) {
|
||||
func (m *metadataTracker) updateSeqLocked(dev protocol.DeviceID, f protocol.FileInfo) {
|
||||
if dev == protocol.GlobalDeviceID {
|
||||
return
|
||||
}
|
||||
@@ -246,7 +258,7 @@ func (m *metadataTracker) updateSeqLocked(dev protocol.DeviceID, f protocol.File
|
||||
}
|
||||
}
|
||||
|
||||
func (m *metadataTracker) addFileLocked(dev protocol.DeviceID, flag uint32, f protocol.FileIntf) {
|
||||
func (m *metadataTracker) addFileLocked(dev protocol.DeviceID, flag uint32, f protocol.FileInfo) {
|
||||
cp := m.countsPtr(dev, flag)
|
||||
|
||||
switch {
|
||||
@@ -263,7 +275,7 @@ func (m *metadataTracker) addFileLocked(dev protocol.DeviceID, flag uint32, f pr
|
||||
}
|
||||
|
||||
// removeFile removes a file from the counts
|
||||
func (m *metadataTracker) removeFile(dev protocol.DeviceID, f protocol.FileIntf) {
|
||||
func (m *metadataTracker) removeFile(dev protocol.DeviceID, f protocol.FileInfo) {
|
||||
m.mut.Lock()
|
||||
defer m.mut.Unlock()
|
||||
|
||||
@@ -271,7 +283,7 @@ func (m *metadataTracker) removeFile(dev protocol.DeviceID, f protocol.FileIntf)
|
||||
}
|
||||
|
||||
// removeNeeded removes a file from the needed counts
|
||||
func (m *metadataTracker) removeNeeded(dev protocol.DeviceID, f protocol.FileIntf) {
|
||||
func (m *metadataTracker) removeNeeded(dev protocol.DeviceID, f protocol.FileInfo) {
|
||||
m.mut.Lock()
|
||||
defer m.mut.Unlock()
|
||||
|
||||
@@ -280,7 +292,7 @@ func (m *metadataTracker) removeNeeded(dev protocol.DeviceID, f protocol.FileInt
|
||||
m.removeFileLocked(dev, needFlag, f)
|
||||
}
|
||||
|
||||
func (m *metadataTracker) removeFileLocked(dev protocol.DeviceID, flag uint32, f protocol.FileIntf) {
|
||||
func (m *metadataTracker) removeFileLocked(dev protocol.DeviceID, flag uint32, f protocol.FileInfo) {
|
||||
cp := m.countsPtr(dev, flag)
|
||||
|
||||
switch {
|
||||
@@ -325,7 +337,7 @@ func (m *metadataTracker) resetAll(dev protocol.DeviceID) {
|
||||
m.mut.Lock()
|
||||
m.dirty = true
|
||||
for i, c := range m.counts.Counts {
|
||||
if bytes.Equal(c.DeviceID, dev[:]) {
|
||||
if c.DeviceID == dev {
|
||||
if c.LocalFlags != needFlag {
|
||||
m.counts.Counts[i] = Counts{
|
||||
DeviceID: c.DeviceID,
|
||||
@@ -346,7 +358,7 @@ func (m *metadataTracker) resetCounts(dev protocol.DeviceID) {
|
||||
m.dirty = true
|
||||
|
||||
for i, c := range m.counts.Counts {
|
||||
if bytes.Equal(c.DeviceID, dev[:]) {
|
||||
if c.DeviceID == dev {
|
||||
m.counts.Counts[i] = Counts{
|
||||
DeviceID: c.DeviceID,
|
||||
Sequence: c.Sequence,
|
||||
@@ -419,14 +431,10 @@ func (m *countsMap) devices() []protocol.DeviceID {
|
||||
|
||||
for _, dev := range m.counts.Counts {
|
||||
if dev.Sequence > 0 {
|
||||
id, err := protocol.DeviceIDFromBytes(dev.DeviceID)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if id == protocol.GlobalDeviceID || id == protocol.LocalDeviceID {
|
||||
if dev.DeviceID == protocol.GlobalDeviceID || dev.DeviceID == protocol.LocalDeviceID {
|
||||
continue
|
||||
}
|
||||
devs = append(devs, id)
|
||||
devs = append(devs, dev.DeviceID)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+49
-14
@@ -10,21 +10,56 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
|
||||
"github.com/syncthing/syncthing/internal/gen/dbproto"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
)
|
||||
|
||||
type ObservedFolder struct {
|
||||
Time time.Time
|
||||
Label string
|
||||
ReceiveEncrypted bool
|
||||
RemoteEncrypted bool
|
||||
}
|
||||
|
||||
func (o *ObservedFolder) toWire() *dbproto.ObservedFolder {
|
||||
return &dbproto.ObservedFolder{
|
||||
Time: timestamppb.New(o.Time),
|
||||
Label: o.Label,
|
||||
ReceiveEncrypted: o.ReceiveEncrypted,
|
||||
RemoteEncrypted: o.RemoteEncrypted,
|
||||
}
|
||||
}
|
||||
|
||||
func (o *ObservedFolder) fromWire(w *dbproto.ObservedFolder) {
|
||||
o.Time = w.GetTime().AsTime()
|
||||
o.Label = w.GetLabel()
|
||||
o.ReceiveEncrypted = w.GetReceiveEncrypted()
|
||||
o.RemoteEncrypted = w.GetRemoteEncrypted()
|
||||
}
|
||||
|
||||
type ObservedDevice struct {
|
||||
Time time.Time
|
||||
Name string
|
||||
Address string
|
||||
}
|
||||
|
||||
func (o *ObservedDevice) fromWire(w *dbproto.ObservedDevice) {
|
||||
o.Time = w.GetTime().AsTime()
|
||||
o.Name = w.GetName()
|
||||
o.Address = w.GetAddress()
|
||||
}
|
||||
|
||||
func (db *Lowlevel) AddOrUpdatePendingDevice(device protocol.DeviceID, name, address string) error {
|
||||
key := db.keyer.GeneratePendingDeviceKey(nil, device[:])
|
||||
od := ObservedDevice{
|
||||
Time: time.Now().Truncate(time.Second),
|
||||
od := &dbproto.ObservedDevice{
|
||||
Time: timestamppb.New(time.Now().Truncate(time.Second)),
|
||||
Name: name,
|
||||
Address: address,
|
||||
}
|
||||
bs, err := od.Marshal()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return db.Put(key, bs)
|
||||
return db.Put(key, mustMarshal(od))
|
||||
}
|
||||
|
||||
func (db *Lowlevel) RemovePendingDevice(device protocol.DeviceID) error {
|
||||
@@ -44,13 +79,15 @@ func (db *Lowlevel) PendingDevices() (map[protocol.DeviceID]ObservedDevice, erro
|
||||
for iter.Next() {
|
||||
keyDev := db.keyer.DeviceFromPendingDeviceKey(iter.Key())
|
||||
deviceID, err := protocol.DeviceIDFromBytes(keyDev)
|
||||
var protoD dbproto.ObservedDevice
|
||||
var od ObservedDevice
|
||||
if err != nil {
|
||||
goto deleteKey
|
||||
}
|
||||
if err = od.Unmarshal(iter.Value()); err != nil {
|
||||
if err = proto.Unmarshal(iter.Value(), &protoD); err != nil {
|
||||
goto deleteKey
|
||||
}
|
||||
od.fromWire(&protoD)
|
||||
res[deviceID] = od
|
||||
continue
|
||||
deleteKey:
|
||||
@@ -70,11 +107,7 @@ func (db *Lowlevel) AddOrUpdatePendingFolder(id string, of ObservedFolder, devic
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
bs, err := of.Marshal()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return db.Put(key, bs)
|
||||
return db.Put(key, mustMarshal(of.toWire()))
|
||||
}
|
||||
|
||||
// RemovePendingFolderForDevice removes entries for specific folder / device combinations.
|
||||
@@ -139,6 +172,7 @@ func (db *Lowlevel) PendingFoldersForDevice(device protocol.DeviceID) (map[strin
|
||||
for iter.Next() {
|
||||
keyDev, ok := db.keyer.DeviceFromPendingFolderKey(iter.Key())
|
||||
deviceID, err := protocol.DeviceIDFromBytes(keyDev)
|
||||
var protoF dbproto.ObservedFolder
|
||||
var of ObservedFolder
|
||||
var folderID string
|
||||
if !ok || err != nil {
|
||||
@@ -147,7 +181,7 @@ func (db *Lowlevel) PendingFoldersForDevice(device protocol.DeviceID) (map[strin
|
||||
if folderID = string(db.keyer.FolderFromPendingFolderKey(iter.Key())); len(folderID) < 1 {
|
||||
goto deleteKey
|
||||
}
|
||||
if err = of.Unmarshal(iter.Value()); err != nil {
|
||||
if err = proto.Unmarshal(iter.Value(), &protoF); err != nil {
|
||||
goto deleteKey
|
||||
}
|
||||
if _, ok := res[folderID]; !ok {
|
||||
@@ -155,6 +189,7 @@ func (db *Lowlevel) PendingFoldersForDevice(device protocol.DeviceID) (map[strin
|
||||
OfferedBy: map[protocol.DeviceID]ObservedFolder{},
|
||||
}
|
||||
}
|
||||
of.fromWire(&protoF)
|
||||
res[folderID].OfferedBy[deviceID] = of
|
||||
continue
|
||||
deleteKey:
|
||||
|
||||
+16
-846
@@ -7,12 +7,11 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/db/backend"
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
"github.com/syncthing/syncthing/internal/gen/bep"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
)
|
||||
|
||||
@@ -65,6 +64,12 @@ func (db *schemaUpdater) updateSchema() error {
|
||||
return err
|
||||
}
|
||||
|
||||
if prevVersion > 0 && prevVersion < 14 {
|
||||
// This is a database version that is too old to be upgraded directly.
|
||||
// The user will have to upgrade to an older version first.
|
||||
return fmt.Errorf("database version %d is too old to be upgraded directly; step via Syncthing v1.27.0 to upgrade", prevVersion)
|
||||
}
|
||||
|
||||
if prevVersion > dbVersion {
|
||||
err := &databaseDowngradeError{}
|
||||
if minSyncthingVersion, ok, dbErr := miscDB.String("dbMinSyncthingVersion"); dbErr != nil {
|
||||
@@ -89,16 +94,6 @@ func (db *schemaUpdater) updateSchema() error {
|
||||
}
|
||||
|
||||
migrations := []migration{
|
||||
{1, 1, "v0.14.0", db.updateSchema0to1},
|
||||
{2, 2, "v0.14.46", db.updateSchema1to2},
|
||||
{3, 3, "v0.14.48", db.updateSchema2to3},
|
||||
{5, 5, "v0.14.49", db.updateSchemaTo5},
|
||||
{6, 6, "v0.14.50", db.updateSchema5to6},
|
||||
{7, 7, "v0.14.53", db.updateSchema6to7},
|
||||
{9, 9, "v1.4.0", db.updateSchemaTo9},
|
||||
{10, 10, "v1.6.0", db.updateSchemaTo10},
|
||||
{11, 11, "v1.6.0", db.updateSchemaTo11},
|
||||
{13, 13, "v1.7.0", db.updateSchemaTo13},
|
||||
{14, 14, "v1.9.0", db.updateSchemaTo14},
|
||||
{14, 16, "v1.9.0", db.checkRepairMigration},
|
||||
{14, 17, "v1.9.0", db.migration17},
|
||||
@@ -143,571 +138,6 @@ func (*schemaUpdater) writeVersions(m migration, miscDB *NamespacedKV) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *schemaUpdater) updateSchema0to1(_ int) error {
|
||||
t, err := db.newReadWriteTransaction()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer t.close()
|
||||
|
||||
dbi, err := t.NewPrefixIterator([]byte{KeyTypeDevice})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer dbi.Release()
|
||||
|
||||
symlinkConv := 0
|
||||
changedFolders := make(map[string]struct{})
|
||||
ignAdded := 0
|
||||
var gk []byte
|
||||
ro := t.readOnlyTransaction
|
||||
|
||||
for dbi.Next() {
|
||||
folder, ok := db.keyer.FolderFromDeviceFileKey(dbi.Key())
|
||||
if !ok {
|
||||
// not having the folder in the index is bad; delete and continue
|
||||
if err := t.Delete(dbi.Key()); err != nil {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
}
|
||||
device, ok := db.keyer.DeviceFromDeviceFileKey(dbi.Key())
|
||||
if !ok {
|
||||
// not having the device in the index is bad; delete and continue
|
||||
if err := t.Delete(dbi.Key()); err != nil {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
}
|
||||
name := db.keyer.NameFromDeviceFileKey(dbi.Key())
|
||||
|
||||
// Remove files with absolute path (see #4799)
|
||||
if strings.HasPrefix(string(name), "/") {
|
||||
if _, ok := changedFolders[string(folder)]; !ok {
|
||||
changedFolders[string(folder)] = struct{}{}
|
||||
}
|
||||
if err := t.Delete(dbi.Key()); err != nil {
|
||||
return err
|
||||
}
|
||||
gk, err = db.keyer.GenerateGlobalVersionKey(gk, folder, name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fl, err := getGlobalVersionsByKeyBefore11(gk, ro)
|
||||
if backend.IsNotFound(err) {
|
||||
// Shouldn't happen, but not critical.
|
||||
continue
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
_, _ = fl.pop(device)
|
||||
if len(fl.Versions) == 0 {
|
||||
err = t.Delete(gk)
|
||||
} else {
|
||||
err = t.Put(gk, mustMarshal(&fl))
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// Change SYMLINK_FILE and SYMLINK_DIRECTORY types to the current SYMLINK
|
||||
// type (previously SYMLINK_UNKNOWN). It does this for all devices, both
|
||||
// local and remote, and does not reset delta indexes. It shouldn't really
|
||||
// matter what the symlink type is, but this cleans it up for a possible
|
||||
// future when SYMLINK_FILE and SYMLINK_DIRECTORY are no longer understood.
|
||||
var f protocol.FileInfo
|
||||
if err := f.Unmarshal(dbi.Value()); err != nil {
|
||||
// probably can't happen
|
||||
continue
|
||||
}
|
||||
if f.Type == protocol.FileInfoTypeSymlinkDirectory || f.Type == protocol.FileInfoTypeSymlinkFile {
|
||||
f.Type = protocol.FileInfoTypeSymlink
|
||||
bs, err := f.Marshal()
|
||||
if err != nil {
|
||||
panic("can't happen: " + err.Error())
|
||||
}
|
||||
if err := t.Put(dbi.Key(), bs); err != nil {
|
||||
return err
|
||||
}
|
||||
symlinkConv++
|
||||
}
|
||||
|
||||
// Add invalid files to global list
|
||||
if f.IsInvalid() {
|
||||
gk, err = db.keyer.GenerateGlobalVersionKey(gk, folder, name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fl, err := getGlobalVersionsByKeyBefore11(gk, ro)
|
||||
if err != nil && !backend.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
i := sort.Search(len(fl.Versions), func(j int) bool {
|
||||
return fl.Versions[j].Invalid
|
||||
})
|
||||
for ; i < len(fl.Versions); i++ {
|
||||
ordering := fl.Versions[i].Version.Compare(f.Version)
|
||||
shouldInsert := ordering == protocol.Equal
|
||||
if !shouldInsert {
|
||||
shouldInsert, err = shouldInsertBefore(ordering, folder, fl.Versions[i].Device, true, f, ro)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if shouldInsert {
|
||||
nv := FileVersionDeprecated{
|
||||
Device: device,
|
||||
Version: f.Version,
|
||||
Invalid: true,
|
||||
}
|
||||
fl.insertAt(i, nv)
|
||||
if err := t.Put(gk, mustMarshal(&fl)); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, ok := changedFolders[string(folder)]; !ok {
|
||||
changedFolders[string(folder)] = struct{}{}
|
||||
}
|
||||
ignAdded++
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if err := t.Checkpoint(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
dbi.Release()
|
||||
if err != dbi.Error() {
|
||||
return err
|
||||
}
|
||||
|
||||
return t.Commit()
|
||||
}
|
||||
|
||||
// updateSchema1to2 introduces a sequenceKey->deviceKey bucket for local items
|
||||
// to allow iteration in sequence order (simplifies sending indexes).
|
||||
func (db *schemaUpdater) updateSchema1to2(_ int) error {
|
||||
t, err := db.newReadWriteTransaction()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer t.close()
|
||||
|
||||
var sk []byte
|
||||
var dk []byte
|
||||
for _, folderStr := range db.ListFolders() {
|
||||
folder := []byte(folderStr)
|
||||
var putErr error
|
||||
err := t.withHave(folder, protocol.LocalDeviceID[:], nil, true, func(f protocol.FileIntf) bool {
|
||||
sk, putErr = db.keyer.GenerateSequenceKey(sk, folder, f.SequenceNo())
|
||||
if putErr != nil {
|
||||
return false
|
||||
}
|
||||
dk, putErr = db.keyer.GenerateDeviceFileKey(dk, folder, protocol.LocalDeviceID[:], []byte(f.FileName()))
|
||||
if putErr != nil {
|
||||
return false
|
||||
}
|
||||
putErr = t.Put(sk, dk)
|
||||
return putErr == nil
|
||||
})
|
||||
if putErr != nil {
|
||||
return putErr
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return t.Commit()
|
||||
}
|
||||
|
||||
// updateSchema2to3 introduces a needKey->nil bucket for locally needed files.
|
||||
func (db *schemaUpdater) updateSchema2to3(_ int) error {
|
||||
t, err := db.newReadWriteTransaction()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer t.close()
|
||||
|
||||
var nk []byte
|
||||
var dk []byte
|
||||
for _, folderStr := range db.ListFolders() {
|
||||
folder := []byte(folderStr)
|
||||
var putErr error
|
||||
err := withGlobalBefore11(folder, true, func(f protocol.FileIntf) bool {
|
||||
name := []byte(f.FileName())
|
||||
dk, putErr = db.keyer.GenerateDeviceFileKey(dk, folder, protocol.LocalDeviceID[:], name)
|
||||
if putErr != nil {
|
||||
return false
|
||||
}
|
||||
var v protocol.Vector
|
||||
haveFile, ok, err := t.getFileTrunc(dk, true)
|
||||
if err != nil {
|
||||
putErr = err
|
||||
return false
|
||||
}
|
||||
if ok {
|
||||
v = haveFile.FileVersion()
|
||||
}
|
||||
fv := FileVersionDeprecated{
|
||||
Version: f.FileVersion(),
|
||||
Invalid: f.IsInvalid(),
|
||||
Deleted: f.IsDeleted(),
|
||||
}
|
||||
if !needDeprecated(fv, ok, v) {
|
||||
return true
|
||||
}
|
||||
nk, putErr = t.keyer.GenerateNeedFileKey(nk, folder, []byte(f.FileName()))
|
||||
if putErr != nil {
|
||||
return false
|
||||
}
|
||||
putErr = t.Put(nk, nil)
|
||||
return putErr == nil
|
||||
}, t.readOnlyTransaction)
|
||||
if putErr != nil {
|
||||
return putErr
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return t.Commit()
|
||||
}
|
||||
|
||||
// updateSchemaTo5 resets the need bucket due to bugs existing in the v0.14.49
|
||||
// release candidates (dbVersion 3 and 4)
|
||||
// https://github.com/syncthing/syncthing/issues/5007
|
||||
// https://github.com/syncthing/syncthing/issues/5053
|
||||
func (db *schemaUpdater) updateSchemaTo5(prevVersion int) error {
|
||||
if prevVersion != 3 && prevVersion != 4 {
|
||||
return nil
|
||||
}
|
||||
|
||||
t, err := db.newReadWriteTransaction()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var nk []byte
|
||||
for _, folderStr := range db.ListFolders() {
|
||||
nk, err = db.keyer.GenerateNeedFileKey(nk, []byte(folderStr), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := t.deleteKeyPrefix(nk[:keyPrefixLen+keyFolderLen]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := t.Commit(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return db.updateSchema2to3(2)
|
||||
}
|
||||
|
||||
func (db *schemaUpdater) updateSchema5to6(_ int) error {
|
||||
// For every local file with the Invalid bit set, clear the Invalid bit and
|
||||
// set LocalFlags = FlagLocalIgnored.
|
||||
|
||||
t, err := db.newReadWriteTransaction()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer t.close()
|
||||
|
||||
var dk []byte
|
||||
|
||||
for _, folderStr := range db.ListFolders() {
|
||||
folder := []byte(folderStr)
|
||||
var iterErr error
|
||||
err := t.withHave(folder, protocol.LocalDeviceID[:], nil, false, func(f protocol.FileIntf) bool {
|
||||
if !f.IsInvalid() {
|
||||
return true
|
||||
}
|
||||
|
||||
fi := f.(protocol.FileInfo)
|
||||
fi.RawInvalid = false
|
||||
fi.LocalFlags = protocol.FlagLocalIgnored
|
||||
bs, _ := fi.Marshal()
|
||||
|
||||
dk, iterErr = db.keyer.GenerateDeviceFileKey(dk, folder, protocol.LocalDeviceID[:], []byte(fi.Name))
|
||||
if iterErr != nil {
|
||||
return false
|
||||
}
|
||||
if iterErr = t.Put(dk, bs); iterErr != nil {
|
||||
return false
|
||||
}
|
||||
iterErr = t.Checkpoint()
|
||||
return iterErr == nil
|
||||
})
|
||||
if iterErr != nil {
|
||||
return iterErr
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return t.Commit()
|
||||
}
|
||||
|
||||
// updateSchema6to7 checks whether all currently locally needed files are really
|
||||
// needed and removes them if not.
|
||||
func (db *schemaUpdater) updateSchema6to7(_ int) error {
|
||||
t, err := db.newReadWriteTransaction()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer t.close()
|
||||
|
||||
var gk []byte
|
||||
var nk []byte
|
||||
|
||||
for _, folderStr := range db.ListFolders() {
|
||||
folder := []byte(folderStr)
|
||||
var delErr error
|
||||
err := withNeedLocalBefore11(folder, false, func(f protocol.FileIntf) bool {
|
||||
name := []byte(f.FileName())
|
||||
gk, delErr = db.keyer.GenerateGlobalVersionKey(gk, folder, name)
|
||||
if delErr != nil {
|
||||
return false
|
||||
}
|
||||
svl, err := t.Get(gk)
|
||||
if err != nil {
|
||||
// If there is no global list, we hardly need it.
|
||||
key, err := t.keyer.GenerateNeedFileKey(nk, folder, name)
|
||||
if err != nil {
|
||||
delErr = err
|
||||
return false
|
||||
}
|
||||
delErr = t.Delete(key)
|
||||
return delErr == nil
|
||||
}
|
||||
var fl VersionListDeprecated
|
||||
err = fl.Unmarshal(svl)
|
||||
if err != nil {
|
||||
// This can't happen, but it's ignored everywhere else too,
|
||||
// so lets not act on it.
|
||||
return true
|
||||
}
|
||||
globalFV := FileVersionDeprecated{
|
||||
Version: f.FileVersion(),
|
||||
Invalid: f.IsInvalid(),
|
||||
Deleted: f.IsDeleted(),
|
||||
}
|
||||
|
||||
if localFV, haveLocalFV := fl.Get(protocol.LocalDeviceID[:]); !needDeprecated(globalFV, haveLocalFV, localFV.Version) {
|
||||
key, err := t.keyer.GenerateNeedFileKey(nk, folder, name)
|
||||
if err != nil {
|
||||
delErr = err
|
||||
return false
|
||||
}
|
||||
delErr = t.Delete(key)
|
||||
}
|
||||
return delErr == nil
|
||||
}, t.readOnlyTransaction)
|
||||
if delErr != nil {
|
||||
return delErr
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := t.Checkpoint(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return t.Commit()
|
||||
}
|
||||
|
||||
func (db *schemaUpdater) updateSchemaTo9(_ int) error {
|
||||
// Loads and rewrites all files with blocks, to deduplicate block lists.
|
||||
|
||||
t, err := db.newReadWriteTransaction()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer t.close()
|
||||
|
||||
if err := rewriteFiles(t); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
db.recordTime(indirectGCTimeKey)
|
||||
|
||||
return t.Commit()
|
||||
}
|
||||
|
||||
func rewriteFiles(t readWriteTransaction) error {
|
||||
it, err := t.NewPrefixIterator([]byte{KeyTypeDevice})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer it.Release()
|
||||
for it.Next() {
|
||||
intf, err := t.unmarshalTrunc(it.Value(), false)
|
||||
if backend.IsNotFound(err) {
|
||||
// Unmarshal error due to missing parts (block list), probably
|
||||
// due to a bad migration in a previous RC. Drop this key, as
|
||||
// getFile would anyway return this as a "not found" in the
|
||||
// normal flow of things.
|
||||
if err := t.Delete(it.Key()); err != nil {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
fi := intf.(protocol.FileInfo)
|
||||
if fi.Blocks == nil {
|
||||
continue
|
||||
}
|
||||
if err := t.putFile(it.Key(), fi); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := t.Checkpoint(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
it.Release()
|
||||
return it.Error()
|
||||
}
|
||||
|
||||
func (db *schemaUpdater) updateSchemaTo10(_ int) error {
|
||||
// Rewrites global lists to include a Deleted flag.
|
||||
|
||||
t, err := db.newReadWriteTransaction()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer t.close()
|
||||
|
||||
var buf []byte
|
||||
|
||||
for _, folderStr := range db.ListFolders() {
|
||||
folder := []byte(folderStr)
|
||||
|
||||
buf, err = t.keyer.GenerateGlobalVersionKey(buf, folder, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
buf = globalVersionKey(buf).WithoutName()
|
||||
dbi, err := t.NewPrefixIterator(buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer dbi.Release()
|
||||
|
||||
for dbi.Next() {
|
||||
var vl VersionListDeprecated
|
||||
if err := vl.Unmarshal(dbi.Value()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
changed := false
|
||||
name := t.keyer.NameFromGlobalVersionKey(dbi.Key())
|
||||
|
||||
for i, fv := range vl.Versions {
|
||||
buf, err = t.keyer.GenerateDeviceFileKey(buf, folder, fv.Device, name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
f, ok, err := t.getFileTrunc(buf, true)
|
||||
if !ok {
|
||||
return errEntryFromGlobalMissing
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if f.IsDeleted() {
|
||||
vl.Versions[i].Deleted = true
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
|
||||
if changed {
|
||||
if err := t.Put(dbi.Key(), mustMarshal(&vl)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := t.Checkpoint(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
dbi.Release()
|
||||
}
|
||||
|
||||
// Trigger metadata recalc
|
||||
if err := t.deleteKeyPrefix([]byte{KeyTypeFolderMeta}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return t.Commit()
|
||||
}
|
||||
|
||||
func (db *schemaUpdater) updateSchemaTo11(_ int) error {
|
||||
// Populates block list map for every folder.
|
||||
|
||||
t, err := db.newReadWriteTransaction()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer t.close()
|
||||
|
||||
var dk []byte
|
||||
for _, folderStr := range db.ListFolders() {
|
||||
folder := []byte(folderStr)
|
||||
var putErr error
|
||||
err := t.withHave(folder, protocol.LocalDeviceID[:], nil, true, func(fi protocol.FileIntf) bool {
|
||||
f := fi.(FileInfoTruncated)
|
||||
if f.IsDirectory() || f.IsDeleted() || f.IsSymlink() || f.IsInvalid() || f.BlocksHash == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
name := []byte(f.FileName())
|
||||
dk, putErr = db.keyer.GenerateBlockListMapKey(dk, folder, f.BlocksHash, name)
|
||||
if putErr != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if putErr = t.Put(dk, nil); putErr != nil {
|
||||
return false
|
||||
}
|
||||
putErr = t.Checkpoint()
|
||||
return putErr == nil
|
||||
})
|
||||
if putErr != nil {
|
||||
return putErr
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return t.Commit()
|
||||
}
|
||||
|
||||
func (db *schemaUpdater) updateSchemaTo13(prev int) error {
|
||||
// Loads and rewrites all files, to deduplicate version vectors.
|
||||
|
||||
t, err := db.newReadWriteTransaction()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer t.close()
|
||||
|
||||
if prev < 12 {
|
||||
if err := rewriteFiles(t); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := rewriteGlobals(t); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return t.Commit()
|
||||
}
|
||||
|
||||
func (db *schemaUpdater) updateSchemaTo14(_ int) error {
|
||||
// Checks for missing blocks and marks those entries as requiring a
|
||||
// rehash/being invalid. The db is checked/repaired afterwards, i.e.
|
||||
@@ -737,10 +167,11 @@ func (db *schemaUpdater) updateSchemaTo14(_ int) error {
|
||||
}
|
||||
defer it.Release()
|
||||
for it.Next() {
|
||||
var fi protocol.FileInfo
|
||||
if err := fi.Unmarshal(it.Value()); err != nil {
|
||||
var bepf bep.FileInfo
|
||||
if err := proto.Unmarshal(it.Value(), &bepf); err != nil {
|
||||
return err
|
||||
}
|
||||
fi := protocol.FileInfoFromDB(&bepf)
|
||||
if len(fi.Blocks) > 0 || len(fi.BlocksHash) == 0 {
|
||||
continue
|
||||
}
|
||||
@@ -808,12 +239,11 @@ func (db *schemaUpdater) migration17(prev int) error {
|
||||
return db.updateLocalFiles(folder, fs, meta)
|
||||
})
|
||||
var innerErr error
|
||||
err = t.withHave(folder, protocol.LocalDeviceID[:], nil, false, func(fi protocol.FileIntf) bool {
|
||||
err = t.withHave(folder, protocol.LocalDeviceID[:], nil, false, func(fi protocol.FileInfo) bool {
|
||||
if fi.IsInvalid() && fi.FileLocalFlags() == 0 {
|
||||
f := fi.(protocol.FileInfo)
|
||||
f.SetMustRescan()
|
||||
f.Version = protocol.Vector{}
|
||||
batch.Append(f)
|
||||
fi.SetMustRescan()
|
||||
fi.Version = protocol.Vector{}
|
||||
batch.Append(fi)
|
||||
innerErr = batch.FlushIfFull()
|
||||
return innerErr == nil
|
||||
}
|
||||
@@ -839,263 +269,3 @@ func (db *schemaUpdater) dropAllIndexIDsMigration(_ int) error {
|
||||
func (db *schemaUpdater) dropOutgoingIndexIDsMigration(_ int) error {
|
||||
return db.dropOtherDeviceIndexIDs()
|
||||
}
|
||||
|
||||
func rewriteGlobals(t readWriteTransaction) error {
|
||||
it, err := t.NewPrefixIterator([]byte{KeyTypeGlobal})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer it.Release()
|
||||
|
||||
for it.Next() {
|
||||
var vl VersionListDeprecated
|
||||
if err := vl.Unmarshal(it.Value()); err != nil {
|
||||
// If we crashed during an earlier migration, some version
|
||||
// lists might already be in the new format: Skip those.
|
||||
var nvl VersionList
|
||||
if nerr := nvl.Unmarshal(it.Value()); nerr == nil {
|
||||
continue
|
||||
}
|
||||
return err
|
||||
}
|
||||
if len(vl.Versions) == 0 {
|
||||
if err := t.Delete(it.Key()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
newVl := convertVersionList(vl)
|
||||
if err := t.Put(it.Key(), mustMarshal(&newVl)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := t.Checkpoint(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return it.Error()
|
||||
}
|
||||
|
||||
func convertVersionList(vl VersionListDeprecated) VersionList {
|
||||
var newVl VersionList
|
||||
var newPos, oldPos int
|
||||
var lastVersion protocol.Vector
|
||||
|
||||
for _, fv := range vl.Versions {
|
||||
if fv.Invalid {
|
||||
break
|
||||
}
|
||||
oldPos++
|
||||
if len(newVl.RawVersions) > 0 && lastVersion.Equal(fv.Version) {
|
||||
newVl.RawVersions[newPos].Devices = append(newVl.RawVersions[newPos].Devices, fv.Device)
|
||||
continue
|
||||
}
|
||||
newPos = len(newVl.RawVersions)
|
||||
newVl.RawVersions = append(newVl.RawVersions, newFileVersion(fv.Device, fv.Version, false, fv.Deleted))
|
||||
lastVersion = fv.Version
|
||||
}
|
||||
|
||||
if oldPos == len(vl.Versions) {
|
||||
return newVl
|
||||
}
|
||||
|
||||
if len(newVl.RawVersions) == 0 {
|
||||
fv := vl.Versions[oldPos]
|
||||
newVl.RawVersions = []FileVersion{newFileVersion(fv.Device, fv.Version, true, fv.Deleted)}
|
||||
oldPos++
|
||||
}
|
||||
newPos = 0
|
||||
outer:
|
||||
for _, fv := range vl.Versions[oldPos:] {
|
||||
for _, nfv := range newVl.RawVersions[newPos:] {
|
||||
switch nfv.Version.Compare(fv.Version) {
|
||||
case protocol.Equal:
|
||||
newVl.RawVersions[newPos].InvalidDevices = append(newVl.RawVersions[newPos].InvalidDevices, fv.Device)
|
||||
continue outer
|
||||
case protocol.Lesser:
|
||||
newVl.insertAt(newPos, newFileVersion(fv.Device, fv.Version, true, fv.Deleted))
|
||||
continue outer
|
||||
case protocol.ConcurrentLesser, protocol.ConcurrentGreater:
|
||||
// The version is invalid, i.e. it looses anyway,
|
||||
// no need to check/get the conflicting file.
|
||||
}
|
||||
newPos++
|
||||
}
|
||||
// Couldn't insert into any existing versions
|
||||
newVl.RawVersions = append(newVl.RawVersions, newFileVersion(fv.Device, fv.Version, true, fv.Deleted))
|
||||
newPos++
|
||||
}
|
||||
|
||||
return newVl
|
||||
}
|
||||
|
||||
func getGlobalVersionsByKeyBefore11(key []byte, t readOnlyTransaction) (VersionListDeprecated, error) {
|
||||
bs, err := t.Get(key)
|
||||
if err != nil {
|
||||
return VersionListDeprecated{}, err
|
||||
}
|
||||
|
||||
var vl VersionListDeprecated
|
||||
if err := vl.Unmarshal(bs); err != nil {
|
||||
return VersionListDeprecated{}, err
|
||||
}
|
||||
|
||||
return vl, nil
|
||||
}
|
||||
|
||||
func withGlobalBefore11(folder []byte, truncate bool, fn Iterator, t readOnlyTransaction) error {
|
||||
key, err := t.keyer.GenerateGlobalVersionKey(nil, folder, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dbi, err := t.NewPrefixIterator(key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer dbi.Release()
|
||||
|
||||
var dk []byte
|
||||
for dbi.Next() {
|
||||
name := t.keyer.NameFromGlobalVersionKey(dbi.Key())
|
||||
|
||||
var vl VersionListDeprecated
|
||||
if err := vl.Unmarshal(dbi.Value()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dk, err = t.keyer.GenerateDeviceFileKey(dk, folder, vl.Versions[0].Device, name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
f, ok, err := t.getFileTrunc(dk, truncate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
if !fn(f) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return dbi.Error()
|
||||
}
|
||||
|
||||
func withNeedLocalBefore11(folder []byte, truncate bool, fn Iterator, t readOnlyTransaction) error {
|
||||
key, err := t.keyer.GenerateNeedFileKey(nil, folder, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dbi, err := t.NewPrefixIterator(key.WithoutName())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer dbi.Release()
|
||||
|
||||
var keyBuf []byte
|
||||
var f protocol.FileIntf
|
||||
var ok bool
|
||||
for dbi.Next() {
|
||||
keyBuf, f, ok, err = getGlobalBefore11(keyBuf, folder, t.keyer.NameFromGlobalVersionKey(dbi.Key()), truncate, t)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if !fn(f) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return dbi.Error()
|
||||
}
|
||||
|
||||
func getGlobalBefore11(keyBuf, folder, file []byte, truncate bool, t readOnlyTransaction) ([]byte, protocol.FileIntf, bool, error) {
|
||||
keyBuf, err := t.keyer.GenerateGlobalVersionKey(keyBuf, folder, file)
|
||||
if err != nil {
|
||||
return nil, nil, false, err
|
||||
}
|
||||
bs, err := t.Get(keyBuf)
|
||||
if backend.IsNotFound(err) {
|
||||
return keyBuf, nil, false, nil
|
||||
} else if err != nil {
|
||||
return nil, nil, false, err
|
||||
}
|
||||
var vl VersionListDeprecated
|
||||
if err := vl.Unmarshal(bs); err != nil {
|
||||
return nil, nil, false, err
|
||||
}
|
||||
if len(vl.Versions) == 0 {
|
||||
return nil, nil, false, nil
|
||||
}
|
||||
keyBuf, err = t.keyer.GenerateDeviceFileKey(keyBuf, folder, vl.Versions[0].Device, file)
|
||||
if err != nil {
|
||||
return nil, nil, false, err
|
||||
}
|
||||
fi, ok, err := t.getFileTrunc(keyBuf, truncate)
|
||||
if err != nil || !ok {
|
||||
return keyBuf, nil, false, err
|
||||
}
|
||||
return keyBuf, fi, true, nil
|
||||
}
|
||||
|
||||
func (vl *VersionListDeprecated) String() string {
|
||||
var b bytes.Buffer
|
||||
var id protocol.DeviceID
|
||||
b.WriteString("{")
|
||||
for i, v := range vl.Versions {
|
||||
if i > 0 {
|
||||
b.WriteString(", ")
|
||||
}
|
||||
copy(id[:], v.Device)
|
||||
fmt.Fprintf(&b, "{%v, %v}", v.Version, id)
|
||||
}
|
||||
b.WriteString("}")
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func (vl *VersionListDeprecated) pop(device []byte) (FileVersionDeprecated, int) {
|
||||
for i, v := range vl.Versions {
|
||||
if bytes.Equal(v.Device, device) {
|
||||
vl.Versions = append(vl.Versions[:i], vl.Versions[i+1:]...)
|
||||
return v, i
|
||||
}
|
||||
}
|
||||
return FileVersionDeprecated{}, -1
|
||||
}
|
||||
|
||||
func (vl *VersionListDeprecated) Get(device []byte) (FileVersionDeprecated, bool) {
|
||||
for _, v := range vl.Versions {
|
||||
if bytes.Equal(v.Device, device) {
|
||||
return v, true
|
||||
}
|
||||
}
|
||||
|
||||
return FileVersionDeprecated{}, false
|
||||
}
|
||||
|
||||
func (vl *VersionListDeprecated) insertAt(i int, v FileVersionDeprecated) {
|
||||
vl.Versions = append(vl.Versions, FileVersionDeprecated{})
|
||||
copy(vl.Versions[i+1:], vl.Versions[i:])
|
||||
vl.Versions[i] = v
|
||||
}
|
||||
|
||||
func needDeprecated(global FileVersionDeprecated, haveLocal bool, localVersion protocol.Vector) bool {
|
||||
// We never need an invalid file.
|
||||
if global.Invalid {
|
||||
return false
|
||||
}
|
||||
// We don't need a deleted file if we don't have it.
|
||||
if global.Deleted && !haveLocal {
|
||||
return false
|
||||
}
|
||||
// We don't need the global file if we already have the same version.
|
||||
if haveLocal && localVersion.GreaterEqual(global.Version) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
+53
-24
@@ -13,8 +13,10 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
"github.com/syncthing/syncthing/internal/gen/dbproto"
|
||||
"github.com/syncthing/syncthing/lib/db/backend"
|
||||
"github.com/syncthing/syncthing/lib/fs"
|
||||
"github.com/syncthing/syncthing/lib/osutil"
|
||||
@@ -33,7 +35,7 @@ type FileSet struct {
|
||||
// The Iterator is called with either a protocol.FileInfo or a
|
||||
// FileInfoTruncated (depending on the method) and returns true to
|
||||
// continue iteration, false to stop.
|
||||
type Iterator func(f protocol.FileIntf) bool
|
||||
type Iterator func(f protocol.FileInfo) bool
|
||||
|
||||
func NewFileSet(folder string, db *Lowlevel) (*FileSet, error) {
|
||||
select {
|
||||
@@ -292,26 +294,24 @@ func (s *Snapshot) GetGlobal(file string) (protocol.FileInfo, bool) {
|
||||
if !ok {
|
||||
return protocol.FileInfo{}, false
|
||||
}
|
||||
f := fi.(protocol.FileInfo)
|
||||
f.Name = osutil.NativeFilename(f.Name)
|
||||
return f, true
|
||||
fi.Name = osutil.NativeFilename(fi.Name)
|
||||
return fi, true
|
||||
}
|
||||
|
||||
func (s *Snapshot) GetGlobalTruncated(file string) (FileInfoTruncated, bool) {
|
||||
func (s *Snapshot) GetGlobalTruncated(file string) (protocol.FileInfo, bool) {
|
||||
opStr := fmt.Sprintf("%s GetGlobalTruncated(%v)", s.folder, file)
|
||||
l.Debugf(opStr)
|
||||
_, fi, ok, err := s.t.getGlobal(nil, []byte(s.folder), []byte(osutil.NormalizedFilename(file)), true)
|
||||
if backend.IsClosed(err) {
|
||||
return FileInfoTruncated{}, false
|
||||
return protocol.FileInfo{}, false
|
||||
} else if err != nil {
|
||||
s.fatalError(err, opStr)
|
||||
}
|
||||
if !ok {
|
||||
return FileInfoTruncated{}, false
|
||||
return protocol.FileInfo{}, false
|
||||
}
|
||||
f := fi.(FileInfoTruncated)
|
||||
f.Name = osutil.NativeFilename(f.Name)
|
||||
return f, true
|
||||
fi.Name = osutil.NativeFilename(fi.Name)
|
||||
return fi, true
|
||||
}
|
||||
|
||||
func (s *Snapshot) Availability(file string) []protocol.DeviceID {
|
||||
@@ -326,16 +326,16 @@ func (s *Snapshot) Availability(file string) []protocol.DeviceID {
|
||||
return av
|
||||
}
|
||||
|
||||
func (s *Snapshot) DebugGlobalVersions(file string) VersionList {
|
||||
func (s *Snapshot) DebugGlobalVersions(file string) *DebugVersionList {
|
||||
opStr := fmt.Sprintf("%s DebugGlobalVersions(%v)", s.folder, file)
|
||||
l.Debugf(opStr)
|
||||
vl, err := s.t.getGlobalVersions(nil, []byte(s.folder), []byte(osutil.NormalizedFilename(file)))
|
||||
if backend.IsClosed(err) || backend.IsNotFound(err) {
|
||||
return VersionList{}
|
||||
return nil
|
||||
} else if err != nil {
|
||||
s.fatalError(err, opStr)
|
||||
}
|
||||
return vl
|
||||
return &DebugVersionList{vl}
|
||||
}
|
||||
|
||||
func (s *Snapshot) Sequence(device protocol.DeviceID) int64 {
|
||||
@@ -503,17 +503,9 @@ func normalizeFilenamesAndDropDuplicates(fs []protocol.FileInfo) []protocol.File
|
||||
}
|
||||
|
||||
func nativeFileIterator(fn Iterator) Iterator {
|
||||
return func(fi protocol.FileIntf) bool {
|
||||
switch f := fi.(type) {
|
||||
case protocol.FileInfo:
|
||||
f.Name = osutil.NativeFilename(f.Name)
|
||||
return fn(f)
|
||||
case FileInfoTruncated:
|
||||
f.Name = osutil.NativeFilename(f.Name)
|
||||
return fn(f)
|
||||
default:
|
||||
panic("unknown interface type")
|
||||
}
|
||||
return func(fi protocol.FileInfo) bool {
|
||||
fi.Name = osutil.NativeFilename(fi.Name)
|
||||
return fn(fi)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -522,3 +514,40 @@ func fatalError(err error, opStr string, db *Lowlevel) {
|
||||
l.Warnf("Fatal error: %v: %v", opStr, err)
|
||||
panic(ldbPathRe.ReplaceAllString(err.Error(), "$1 x: "))
|
||||
}
|
||||
|
||||
// DebugFileVersion is the database-internal representation of a file
|
||||
// version, with a nicer string representation, used only by API debug
|
||||
// methods.
|
||||
type DebugVersionList struct {
|
||||
*dbproto.VersionList
|
||||
}
|
||||
|
||||
func (vl DebugVersionList) String() string {
|
||||
var b bytes.Buffer
|
||||
var id protocol.DeviceID
|
||||
b.WriteString("[")
|
||||
for i, v := range vl.Versions {
|
||||
if i > 0 {
|
||||
b.WriteString(", ")
|
||||
}
|
||||
fmt.Fprintf(&b, "{Version:%v, Deleted:%v, Devices:[", protocol.VectorFromWire(v.Version), v.Deleted)
|
||||
for j, dev := range v.Devices {
|
||||
if j > 0 {
|
||||
b.WriteString(", ")
|
||||
}
|
||||
copy(id[:], dev)
|
||||
fmt.Fprint(&b, id.Short())
|
||||
}
|
||||
b.WriteString("], Invalid:[")
|
||||
for j, dev := range v.InvalidDevices {
|
||||
if j > 0 {
|
||||
b.WriteString(", ")
|
||||
}
|
||||
copy(id[:], dev)
|
||||
fmt.Fprint(&b, id.Short())
|
||||
}
|
||||
fmt.Fprint(&b, "]}")
|
||||
}
|
||||
b.WriteString("]")
|
||||
return b.String()
|
||||
}
|
||||
|
||||
+23
-27
@@ -16,6 +16,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/d4l3k/messagediff"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/db"
|
||||
"github.com/syncthing/syncthing/lib/db/backend"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
@@ -48,21 +49,19 @@ func globalList(t testing.TB, s *db.FileSet) []protocol.FileInfo {
|
||||
var fs []protocol.FileInfo
|
||||
snap := snapshot(t, s)
|
||||
defer snap.Release()
|
||||
snap.WithGlobal(func(fi protocol.FileIntf) bool {
|
||||
f := fi.(protocol.FileInfo)
|
||||
fs = append(fs, f)
|
||||
snap.WithGlobal(func(fi protocol.FileInfo) bool {
|
||||
fs = append(fs, fi)
|
||||
return true
|
||||
})
|
||||
return fs
|
||||
}
|
||||
|
||||
func globalListPrefixed(t testing.TB, s *db.FileSet, prefix string) []db.FileInfoTruncated {
|
||||
var fs []db.FileInfoTruncated
|
||||
func globalListPrefixed(t testing.TB, s *db.FileSet, prefix string) []protocol.FileInfo {
|
||||
var fs []protocol.FileInfo
|
||||
snap := snapshot(t, s)
|
||||
defer snap.Release()
|
||||
snap.WithPrefixedGlobalTruncated(prefix, func(fi protocol.FileIntf) bool {
|
||||
f := fi.(db.FileInfoTruncated)
|
||||
fs = append(fs, f)
|
||||
snap.WithPrefixedGlobalTruncated(prefix, func(fi protocol.FileInfo) bool {
|
||||
fs = append(fs, fi)
|
||||
return true
|
||||
})
|
||||
return fs
|
||||
@@ -72,21 +71,19 @@ func haveList(t testing.TB, s *db.FileSet, n protocol.DeviceID) []protocol.FileI
|
||||
var fs []protocol.FileInfo
|
||||
snap := snapshot(t, s)
|
||||
defer snap.Release()
|
||||
snap.WithHave(n, func(fi protocol.FileIntf) bool {
|
||||
f := fi.(protocol.FileInfo)
|
||||
fs = append(fs, f)
|
||||
snap.WithHave(n, func(fi protocol.FileInfo) bool {
|
||||
fs = append(fs, fi)
|
||||
return true
|
||||
})
|
||||
return fs
|
||||
}
|
||||
|
||||
func haveListPrefixed(t testing.TB, s *db.FileSet, n protocol.DeviceID, prefix string) []db.FileInfoTruncated {
|
||||
var fs []db.FileInfoTruncated
|
||||
func haveListPrefixed(t testing.TB, s *db.FileSet, n protocol.DeviceID, prefix string) []protocol.FileInfo {
|
||||
var fs []protocol.FileInfo
|
||||
snap := snapshot(t, s)
|
||||
defer snap.Release()
|
||||
snap.WithPrefixedHaveTruncated(n, prefix, func(fi protocol.FileIntf) bool {
|
||||
f := fi.(db.FileInfoTruncated)
|
||||
fs = append(fs, f)
|
||||
snap.WithPrefixedHaveTruncated(n, prefix, func(fi protocol.FileInfo) bool {
|
||||
fs = append(fs, fi)
|
||||
return true
|
||||
})
|
||||
return fs
|
||||
@@ -96,9 +93,8 @@ func needList(t testing.TB, s *db.FileSet, n protocol.DeviceID) []protocol.FileI
|
||||
var fs []protocol.FileInfo
|
||||
snap := snapshot(t, s)
|
||||
defer snap.Release()
|
||||
snap.WithNeed(n, func(fi protocol.FileIntf) bool {
|
||||
f := fi.(protocol.FileInfo)
|
||||
fs = append(fs, f)
|
||||
snap.WithNeed(n, func(fi protocol.FileInfo) bool {
|
||||
fs = append(fs, fi)
|
||||
return true
|
||||
})
|
||||
return fs
|
||||
@@ -1011,9 +1007,9 @@ func TestWithHaveSequence(t *testing.T) {
|
||||
i := 2
|
||||
snap := snapshot(t, s)
|
||||
defer snap.Release()
|
||||
snap.WithHaveSequence(int64(i), func(fi protocol.FileIntf) bool {
|
||||
if f := fi.(protocol.FileInfo); !f.IsEquivalent(localHave[i-1], 0) {
|
||||
t.Fatalf("Got %v\nExpected %v", f, localHave[i-1])
|
||||
snap.WithHaveSequence(int64(i), func(fi protocol.FileInfo) bool {
|
||||
if !fi.IsEquivalent(localHave[i-1], 0) {
|
||||
t.Fatalf("Got %v\nExpected %v", fi, localHave[i-1])
|
||||
}
|
||||
i++
|
||||
return true
|
||||
@@ -1062,7 +1058,7 @@ loop:
|
||||
default:
|
||||
}
|
||||
snap := snapshot(t, s)
|
||||
snap.WithHaveSequence(prevSeq+1, func(fi protocol.FileIntf) bool {
|
||||
snap.WithHaveSequence(prevSeq+1, func(fi protocol.FileInfo) bool {
|
||||
if fi.SequenceNo() < prevSeq+1 {
|
||||
t.Fatal("Skipped ", prevSeq+1, fi.SequenceNo())
|
||||
}
|
||||
@@ -1540,8 +1536,8 @@ func TestSequenceIndex(t *testing.T) {
|
||||
|
||||
// Start a routine to walk the sequence index and inspect the result.
|
||||
|
||||
seen := make(map[string]protocol.FileIntf)
|
||||
latest := make([]protocol.FileIntf, 0, len(local))
|
||||
seen := make(map[string]protocol.FileInfo)
|
||||
latest := make([]protocol.FileInfo, 0, len(local))
|
||||
var seq int64
|
||||
t0 := time.Now()
|
||||
|
||||
@@ -1552,7 +1548,7 @@ func TestSequenceIndex(t *testing.T) {
|
||||
// update has happened since our last iteration.
|
||||
latest = latest[:0]
|
||||
snap := snapshot(t, s)
|
||||
snap.WithHaveSequence(seq+1, func(f protocol.FileIntf) bool {
|
||||
snap.WithHaveSequence(seq+1, func(f protocol.FileInfo) bool {
|
||||
seen[f.FileName()] = f
|
||||
latest = append(latest, f)
|
||||
seq = f.SequenceNo()
|
||||
@@ -1657,7 +1653,7 @@ func TestUpdateWithOneFileTwice(t *testing.T) {
|
||||
snap := snapshot(t, s)
|
||||
defer snap.Release()
|
||||
count := 0
|
||||
snap.WithHaveSequence(0, func(f protocol.FileIntf) bool {
|
||||
snap.WithHaveSequence(0, func(_ protocol.FileInfo) bool {
|
||||
count++
|
||||
return true
|
||||
})
|
||||
|
||||
+108
-269
@@ -10,172 +10,52 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
"github.com/syncthing/syncthing/internal/gen/dbproto"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
)
|
||||
|
||||
func (f FileInfoTruncated) String() string {
|
||||
switch f.Type {
|
||||
case protocol.FileInfoTypeDirectory:
|
||||
return fmt.Sprintf("Directory{Name:%q, Sequence:%d, Permissions:0%o, ModTime:%v, Version:%v, Deleted:%v, Invalid:%v, LocalFlags:0x%x, NoPermissions:%v}",
|
||||
f.Name, f.Sequence, f.Permissions, f.ModTime(), f.Version, f.Deleted, f.RawInvalid, f.LocalFlags, f.NoPermissions)
|
||||
case protocol.FileInfoTypeFile:
|
||||
return fmt.Sprintf("File{Name:%q, Sequence:%d, Permissions:0%o, ModTime:%v, Version:%v, Length:%d, Deleted:%v, Invalid:%v, LocalFlags:0x%x, NoPermissions:%v, BlockSize:%d}",
|
||||
f.Name, f.Sequence, f.Permissions, f.ModTime(), f.Version, f.Size, f.Deleted, f.RawInvalid, f.LocalFlags, f.NoPermissions, f.RawBlockSize)
|
||||
case protocol.FileInfoTypeSymlink, protocol.FileInfoTypeSymlinkDirectory, protocol.FileInfoTypeSymlinkFile:
|
||||
return fmt.Sprintf("Symlink{Name:%q, Type:%v, Sequence:%d, Version:%v, Deleted:%v, Invalid:%v, LocalFlags:0x%x, NoPermissions:%v, SymlinkTarget:%q}",
|
||||
f.Name, f.Type, f.Sequence, f.Version, f.Deleted, f.RawInvalid, f.LocalFlags, f.NoPermissions, f.SymlinkTarget)
|
||||
default:
|
||||
panic("mystery file type detected")
|
||||
type CountsSet struct {
|
||||
Counts []Counts
|
||||
Created int64 // unix nanos
|
||||
}
|
||||
|
||||
type Counts struct {
|
||||
Files int
|
||||
Directories int
|
||||
Symlinks int
|
||||
Deleted int
|
||||
Bytes int64
|
||||
Sequence int64 // zero for the global state
|
||||
DeviceID protocol.DeviceID // device ID for remote devices, or special values for local/global
|
||||
LocalFlags uint32 // the local flag for this count bucket
|
||||
}
|
||||
|
||||
func (c Counts) toWire() *dbproto.Counts {
|
||||
return &dbproto.Counts{
|
||||
Files: int32(c.Files),
|
||||
Directories: int32(c.Directories),
|
||||
Symlinks: int32(c.Symlinks),
|
||||
Deleted: int32(c.Deleted),
|
||||
Bytes: c.Bytes,
|
||||
Sequence: c.Sequence,
|
||||
DeviceId: c.DeviceID[:],
|
||||
LocalFlags: c.LocalFlags,
|
||||
}
|
||||
}
|
||||
|
||||
func (f FileInfoTruncated) IsDeleted() bool {
|
||||
return f.Deleted
|
||||
}
|
||||
|
||||
func (f FileInfoTruncated) IsInvalid() bool {
|
||||
return f.RawInvalid || f.LocalFlags&protocol.LocalInvalidFlags != 0
|
||||
}
|
||||
|
||||
func (f FileInfoTruncated) IsUnsupported() bool {
|
||||
return f.LocalFlags&protocol.FlagLocalUnsupported != 0
|
||||
}
|
||||
|
||||
func (f FileInfoTruncated) IsIgnored() bool {
|
||||
return f.LocalFlags&protocol.FlagLocalIgnored != 0
|
||||
}
|
||||
|
||||
func (f FileInfoTruncated) MustRescan() bool {
|
||||
return f.LocalFlags&protocol.FlagLocalMustRescan != 0
|
||||
}
|
||||
|
||||
func (f FileInfoTruncated) IsReceiveOnlyChanged() bool {
|
||||
return f.LocalFlags&protocol.FlagLocalReceiveOnly != 0
|
||||
}
|
||||
|
||||
func (f FileInfoTruncated) IsDirectory() bool {
|
||||
return f.Type == protocol.FileInfoTypeDirectory
|
||||
}
|
||||
|
||||
func (f FileInfoTruncated) IsSymlink() bool {
|
||||
switch f.Type {
|
||||
case protocol.FileInfoTypeSymlink, protocol.FileInfoTypeSymlinkDirectory, protocol.FileInfoTypeSymlinkFile:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (f FileInfoTruncated) ShouldConflict() bool {
|
||||
return f.LocalFlags&protocol.LocalConflictFlags != 0
|
||||
}
|
||||
|
||||
func (f FileInfoTruncated) HasPermissionBits() bool {
|
||||
return !f.NoPermissions
|
||||
}
|
||||
|
||||
func (f FileInfoTruncated) FileSize() int64 {
|
||||
if f.Deleted {
|
||||
return 0
|
||||
}
|
||||
if f.IsDirectory() || f.IsSymlink() {
|
||||
return protocol.SyntheticDirectorySize
|
||||
}
|
||||
return f.Size
|
||||
}
|
||||
|
||||
func (f FileInfoTruncated) BlockSize() int {
|
||||
if f.RawBlockSize == 0 {
|
||||
return protocol.MinBlockSize
|
||||
}
|
||||
return int(f.RawBlockSize)
|
||||
}
|
||||
|
||||
func (f FileInfoTruncated) FileName() string {
|
||||
return f.Name
|
||||
}
|
||||
|
||||
func (f FileInfoTruncated) FileLocalFlags() uint32 {
|
||||
return f.LocalFlags
|
||||
}
|
||||
|
||||
func (f FileInfoTruncated) ModTime() time.Time {
|
||||
return time.Unix(f.ModifiedS, int64(f.ModifiedNs))
|
||||
}
|
||||
|
||||
func (f FileInfoTruncated) SequenceNo() int64 {
|
||||
return f.Sequence
|
||||
}
|
||||
|
||||
func (f FileInfoTruncated) FileVersion() protocol.Vector {
|
||||
return f.Version
|
||||
}
|
||||
|
||||
func (f FileInfoTruncated) FileType() protocol.FileInfoType {
|
||||
return f.Type
|
||||
}
|
||||
|
||||
func (f FileInfoTruncated) FilePermissions() uint32 {
|
||||
return f.Permissions
|
||||
}
|
||||
|
||||
func (f FileInfoTruncated) FileModifiedBy() protocol.ShortID {
|
||||
return f.ModifiedBy
|
||||
}
|
||||
|
||||
func (f FileInfoTruncated) PlatformData() protocol.PlatformData {
|
||||
return f.Platform
|
||||
}
|
||||
|
||||
func (f FileInfoTruncated) InodeChangeTime() time.Time {
|
||||
return time.Unix(0, f.InodeChangeNs)
|
||||
}
|
||||
|
||||
func (f FileInfoTruncated) FileBlocksHash() []byte {
|
||||
return f.BlocksHash
|
||||
}
|
||||
|
||||
func (f FileInfoTruncated) ConvertToIgnoredFileInfo() protocol.FileInfo {
|
||||
file := f.copyToFileInfo()
|
||||
file.SetIgnored()
|
||||
return file
|
||||
}
|
||||
|
||||
func (f FileInfoTruncated) ConvertToDeletedFileInfo(by protocol.ShortID) protocol.FileInfo {
|
||||
file := f.copyToFileInfo()
|
||||
file.SetDeleted(by)
|
||||
return file
|
||||
}
|
||||
|
||||
// ConvertDeletedToFileInfo converts a deleted truncated file info to a regular file info
|
||||
func (f FileInfoTruncated) ConvertDeletedToFileInfo() protocol.FileInfo {
|
||||
if !f.Deleted {
|
||||
panic("ConvertDeletedToFileInfo must only be called on deleted items")
|
||||
}
|
||||
return f.copyToFileInfo()
|
||||
}
|
||||
|
||||
// copyToFileInfo just copies all members of FileInfoTruncated to protocol.FileInfo
|
||||
func (f FileInfoTruncated) copyToFileInfo() protocol.FileInfo {
|
||||
return protocol.FileInfo{
|
||||
Name: f.Name,
|
||||
Size: f.Size,
|
||||
ModifiedS: f.ModifiedS,
|
||||
ModifiedBy: f.ModifiedBy,
|
||||
Version: f.Version,
|
||||
Sequence: f.Sequence,
|
||||
SymlinkTarget: f.SymlinkTarget,
|
||||
BlocksHash: f.BlocksHash,
|
||||
Type: f.Type,
|
||||
Permissions: f.Permissions,
|
||||
ModifiedNs: f.ModifiedNs,
|
||||
RawBlockSize: f.RawBlockSize,
|
||||
LocalFlags: f.LocalFlags,
|
||||
Deleted: f.Deleted,
|
||||
RawInvalid: f.RawInvalid,
|
||||
NoPermissions: f.NoPermissions,
|
||||
func countsFromWire(w *dbproto.Counts) Counts {
|
||||
return Counts{
|
||||
Files: int(w.Files),
|
||||
Directories: int(w.Directories),
|
||||
Symlinks: int(w.Symlinks),
|
||||
Deleted: int(w.Deleted),
|
||||
Bytes: w.Bytes,
|
||||
Sequence: w.Sequence,
|
||||
DeviceID: protocol.DeviceID(w.DeviceId),
|
||||
LocalFlags: w.LocalFlags,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,7 +67,7 @@ func (c Counts) Add(other Counts) Counts {
|
||||
Deleted: c.Deleted + other.Deleted,
|
||||
Bytes: c.Bytes + other.Bytes,
|
||||
Sequence: c.Sequence + other.Sequence,
|
||||
DeviceID: protocol.EmptyDeviceID[:],
|
||||
DeviceID: protocol.EmptyDeviceID,
|
||||
LocalFlags: c.LocalFlags | other.LocalFlags,
|
||||
}
|
||||
}
|
||||
@@ -197,7 +77,6 @@ func (c Counts) TotalItems() int {
|
||||
}
|
||||
|
||||
func (c Counts) String() string {
|
||||
dev, _ := protocol.DeviceIDFromBytes(c.DeviceID)
|
||||
var flags strings.Builder
|
||||
if c.LocalFlags&needFlag != 0 {
|
||||
flags.WriteString("Need")
|
||||
@@ -220,7 +99,7 @@ func (c Counts) String() string {
|
||||
if flags.Len() == 0 {
|
||||
flags.WriteString("---")
|
||||
}
|
||||
return fmt.Sprintf("{Device:%v, Files:%d, Dirs:%d, Symlinks:%d, Del:%d, Bytes:%d, Seq:%d, Flags:%s}", dev, c.Files, c.Directories, c.Symlinks, c.Deleted, c.Bytes, c.Sequence, flags.String())
|
||||
return fmt.Sprintf("{Device:%v, Files:%d, Dirs:%d, Symlinks:%d, Del:%d, Bytes:%d, Seq:%d, Flags:%s}", c.DeviceID, c.Files, c.Directories, c.Symlinks, c.Deleted, c.Bytes, c.Sequence, flags.String())
|
||||
}
|
||||
|
||||
// Equal compares the numbers only, not sequence/dev/flags.
|
||||
@@ -228,80 +107,50 @@ func (c Counts) Equal(o Counts) bool {
|
||||
return c.Files == o.Files && c.Directories == o.Directories && c.Symlinks == o.Symlinks && c.Deleted == o.Deleted && c.Bytes == o.Bytes
|
||||
}
|
||||
|
||||
func (vl VersionList) String() string {
|
||||
var b bytes.Buffer
|
||||
var id protocol.DeviceID
|
||||
b.WriteString("{")
|
||||
for i, v := range vl.RawVersions {
|
||||
if i > 0 {
|
||||
b.WriteString(", ")
|
||||
}
|
||||
fmt.Fprintf(&b, "{Version:%v, Deleted:%v, Devices:{", v.Version, v.Deleted)
|
||||
for j, dev := range v.Devices {
|
||||
if j > 0 {
|
||||
b.WriteString(", ")
|
||||
}
|
||||
copy(id[:], dev)
|
||||
fmt.Fprint(&b, id.Short())
|
||||
}
|
||||
b.WriteString("}, Invalid:{")
|
||||
for j, dev := range v.InvalidDevices {
|
||||
if j > 0 {
|
||||
b.WriteString(", ")
|
||||
}
|
||||
copy(id[:], dev)
|
||||
fmt.Fprint(&b, id.Short())
|
||||
}
|
||||
fmt.Fprint(&b, "}}")
|
||||
}
|
||||
b.WriteString("}")
|
||||
return b.String()
|
||||
}
|
||||
|
||||
// update brings the VersionList up to date with file. It returns the updated
|
||||
// VersionList, a device that has the global/newest version, a device that previously
|
||||
// had the global/newest version, a boolean indicating if the global version has
|
||||
// changed and if any error occurred (only possible in db interaction).
|
||||
func (vl *VersionList) update(folder, device []byte, file protocol.FileIntf, t readOnlyTransaction) (FileVersion, FileVersion, FileVersion, bool, bool, bool, error) {
|
||||
if len(vl.RawVersions) == 0 {
|
||||
func vlUpdate(vl *dbproto.VersionList, folder, device []byte, file protocol.FileInfo, t readOnlyTransaction) (*dbproto.FileVersion, *dbproto.FileVersion, *dbproto.FileVersion, bool, bool, bool, error) {
|
||||
if len(vl.Versions) == 0 {
|
||||
nv := newFileVersion(device, file.FileVersion(), file.IsInvalid(), file.IsDeleted())
|
||||
vl.RawVersions = append(vl.RawVersions, nv)
|
||||
return nv, FileVersion{}, FileVersion{}, false, false, true, nil
|
||||
vl.Versions = append(vl.Versions, nv)
|
||||
return nv, nil, nil, false, false, true, nil
|
||||
}
|
||||
|
||||
// Get the current global (before updating)
|
||||
oldFV, haveOldGlobal := vl.GetGlobal()
|
||||
oldFV = oldFV.copy()
|
||||
oldFV, haveOldGlobal := vlGetGlobal(vl)
|
||||
oldFV = fvCopy(oldFV)
|
||||
|
||||
// Remove ourselves first
|
||||
removedFV, haveRemoved, _ := vl.pop(device)
|
||||
removedFV, haveRemoved, _ := vlPop(vl, device)
|
||||
// Find position and insert the file
|
||||
err := vl.insert(folder, device, file, t)
|
||||
err := vlInsert(vl, folder, device, file, t)
|
||||
if err != nil {
|
||||
return FileVersion{}, FileVersion{}, FileVersion{}, false, false, false, err
|
||||
return nil, nil, nil, false, false, false, err
|
||||
}
|
||||
|
||||
newFV, _ := vl.GetGlobal() // We just inserted something above, can't be empty
|
||||
newFV, _ := vlGetGlobal(vl) // We just inserted something above, can't be empty
|
||||
|
||||
if !haveOldGlobal {
|
||||
return newFV, FileVersion{}, removedFV, false, haveRemoved, true, nil
|
||||
return newFV, nil, removedFV, false, haveRemoved, true, nil
|
||||
}
|
||||
|
||||
globalChanged := true
|
||||
if oldFV.IsInvalid() == newFV.IsInvalid() && oldFV.Version.Equal(newFV.Version) {
|
||||
if fvIsInvalid(oldFV) == fvIsInvalid(newFV) && protocol.VectorFromWire(oldFV.Version).Equal(protocol.VectorFromWire(newFV.Version)) {
|
||||
globalChanged = false
|
||||
}
|
||||
|
||||
return newFV, oldFV, removedFV, true, haveRemoved, globalChanged, nil
|
||||
}
|
||||
|
||||
func (vl *VersionList) insert(folder, device []byte, file protocol.FileIntf, t readOnlyTransaction) error {
|
||||
func vlInsert(vl *dbproto.VersionList, folder, device []byte, file protocol.FileInfo, t readOnlyTransaction) error {
|
||||
var added bool
|
||||
var err error
|
||||
i := 0
|
||||
for ; i < len(vl.RawVersions); i++ {
|
||||
for ; i < len(vl.Versions); i++ {
|
||||
// Insert our new version
|
||||
added, err = vl.checkInsertAt(i, folder, device, file, t)
|
||||
added, err = vlCheckInsertAt(vl, i, folder, device, file, t)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -309,80 +158,76 @@ func (vl *VersionList) insert(folder, device []byte, file protocol.FileIntf, t r
|
||||
break
|
||||
}
|
||||
}
|
||||
if i == len(vl.RawVersions) {
|
||||
if i == len(vl.Versions) {
|
||||
// Append to the end
|
||||
vl.RawVersions = append(vl.RawVersions, newFileVersion(device, file.FileVersion(), file.IsInvalid(), file.IsDeleted()))
|
||||
vl.Versions = append(vl.Versions, newFileVersion(device, file.FileVersion(), file.IsInvalid(), file.IsDeleted()))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vl *VersionList) insertAt(i int, v FileVersion) {
|
||||
vl.RawVersions = append(vl.RawVersions, FileVersion{})
|
||||
copy(vl.RawVersions[i+1:], vl.RawVersions[i:])
|
||||
vl.RawVersions[i] = v
|
||||
func vlInsertAt(vl *dbproto.VersionList, i int, v *dbproto.FileVersion) {
|
||||
vl.Versions = append(vl.Versions, &dbproto.FileVersion{})
|
||||
copy(vl.Versions[i+1:], vl.Versions[i:])
|
||||
vl.Versions[i] = v
|
||||
}
|
||||
|
||||
// pop removes the given device from the VersionList and returns the FileVersion
|
||||
// before removing the device, whether it was found/removed at all and whether
|
||||
// the global changed in the process.
|
||||
func (vl *VersionList) pop(device []byte) (FileVersion, bool, bool) {
|
||||
invDevice, i, j, ok := vl.findDevice(device)
|
||||
func vlPop(vl *dbproto.VersionList, device []byte) (*dbproto.FileVersion, bool, bool) {
|
||||
invDevice, i, j, ok := vlFindDevice(vl, device)
|
||||
if !ok {
|
||||
return FileVersion{}, false, false
|
||||
return nil, false, false
|
||||
}
|
||||
globalPos := vl.findGlobal()
|
||||
globalPos := vlFindGlobal(vl)
|
||||
|
||||
if vl.RawVersions[i].deviceCount() == 1 {
|
||||
fv := vl.RawVersions[i]
|
||||
vl.popVersionAt(i)
|
||||
fv := vl.Versions[i]
|
||||
if fvDeviceCount(fv) == 1 {
|
||||
vlPopVersionAt(vl, i)
|
||||
return fv, true, globalPos == i
|
||||
}
|
||||
|
||||
oldFV := vl.RawVersions[i].copy()
|
||||
oldFV := fvCopy(fv)
|
||||
if invDevice {
|
||||
vl.RawVersions[i].InvalidDevices = popDeviceAt(vl.RawVersions[i].InvalidDevices, j)
|
||||
vl.Versions[i].InvalidDevices = popDeviceAt(vl.Versions[i].InvalidDevices, j)
|
||||
return oldFV, true, false
|
||||
}
|
||||
vl.RawVersions[i].Devices = popDeviceAt(vl.RawVersions[i].Devices, j)
|
||||
vl.Versions[i].Devices = popDeviceAt(vl.Versions[i].Devices, j)
|
||||
// If the last valid device of the previous global was removed above,
|
||||
// the global changed.
|
||||
return oldFV, true, len(vl.RawVersions[i].Devices) == 0 && globalPos == i
|
||||
return oldFV, true, len(vl.Versions[i].Devices) == 0 && globalPos == i
|
||||
}
|
||||
|
||||
// Get returns a FileVersion that contains the given device and whether it has
|
||||
// been found at all.
|
||||
func (vl *VersionList) Get(device []byte) (FileVersion, bool) {
|
||||
_, i, _, ok := vl.findDevice(device)
|
||||
func vlGet(vl *dbproto.VersionList, device []byte) (*dbproto.FileVersion, bool) {
|
||||
_, i, _, ok := vlFindDevice(vl, device)
|
||||
if !ok {
|
||||
return FileVersion{}, false
|
||||
return &dbproto.FileVersion{}, false
|
||||
}
|
||||
return vl.RawVersions[i], true
|
||||
return vl.Versions[i], true
|
||||
}
|
||||
|
||||
// GetGlobal returns the current global FileVersion. The returned FileVersion
|
||||
// may be invalid, if all FileVersions are invalid. Returns false only if
|
||||
// VersionList is empty.
|
||||
func (vl *VersionList) GetGlobal() (FileVersion, bool) {
|
||||
i := vl.findGlobal()
|
||||
func vlGetGlobal(vl *dbproto.VersionList) (*dbproto.FileVersion, bool) {
|
||||
i := vlFindGlobal(vl)
|
||||
if i == -1 {
|
||||
return FileVersion{}, false
|
||||
return nil, false
|
||||
}
|
||||
return vl.RawVersions[i], true
|
||||
}
|
||||
|
||||
func (vl *VersionList) Empty() bool {
|
||||
return len(vl.RawVersions) == 0
|
||||
return vl.Versions[i], true
|
||||
}
|
||||
|
||||
// findGlobal returns the first version that isn't invalid, or if all versions are
|
||||
// invalid just the first version (i.e. 0) or -1, if there's no versions at all.
|
||||
func (vl *VersionList) findGlobal() int {
|
||||
for i, fv := range vl.RawVersions {
|
||||
if !fv.IsInvalid() {
|
||||
func vlFindGlobal(vl *dbproto.VersionList) int {
|
||||
for i := range vl.Versions {
|
||||
if !fvIsInvalid(vl.Versions[i]) {
|
||||
return i
|
||||
}
|
||||
}
|
||||
if len(vl.RawVersions) == 0 {
|
||||
if len(vl.Versions) == 0 {
|
||||
return -1
|
||||
}
|
||||
return 0
|
||||
@@ -391,8 +236,8 @@ func (vl *VersionList) findGlobal() int {
|
||||
// findDevice returns whether the device is in InvalidVersions or Versions and
|
||||
// in InvalidDevices or Devices (true for invalid), the positions in the version
|
||||
// and device slices and whether it has been found at all.
|
||||
func (vl *VersionList) findDevice(device []byte) (bool, int, int, bool) {
|
||||
for i, v := range vl.RawVersions {
|
||||
func vlFindDevice(vl *dbproto.VersionList, device []byte) (bool, int, int, bool) {
|
||||
for i, v := range vl.Versions {
|
||||
if j := deviceIndex(v.Devices, device); j != -1 {
|
||||
return false, i, j, true
|
||||
}
|
||||
@@ -403,30 +248,31 @@ func (vl *VersionList) findDevice(device []byte) (bool, int, int, bool) {
|
||||
return false, -1, -1, false
|
||||
}
|
||||
|
||||
func (vl *VersionList) popVersionAt(i int) {
|
||||
vl.RawVersions = append(vl.RawVersions[:i], vl.RawVersions[i+1:]...)
|
||||
func vlPopVersionAt(vl *dbproto.VersionList, i int) {
|
||||
vl.Versions = append(vl.Versions[:i], vl.Versions[i+1:]...)
|
||||
}
|
||||
|
||||
// checkInsertAt determines if the given device and associated file should be
|
||||
// inserted into the FileVersion at position i or into a new FileVersion at
|
||||
// position i.
|
||||
func (vl *VersionList) checkInsertAt(i int, folder, device []byte, file protocol.FileIntf, t readOnlyTransaction) (bool, error) {
|
||||
ordering := vl.RawVersions[i].Version.Compare(file.FileVersion())
|
||||
func vlCheckInsertAt(vl *dbproto.VersionList, i int, folder, device []byte, file protocol.FileInfo, t readOnlyTransaction) (bool, error) {
|
||||
fv := vl.Versions[i]
|
||||
ordering := protocol.VectorFromWire(fv.Version).Compare(file.FileVersion())
|
||||
if ordering == protocol.Equal {
|
||||
if !file.IsInvalid() {
|
||||
vl.RawVersions[i].Devices = append(vl.RawVersions[i].Devices, device)
|
||||
fv.Devices = append(fv.Devices, device)
|
||||
} else {
|
||||
vl.RawVersions[i].InvalidDevices = append(vl.RawVersions[i].InvalidDevices, device)
|
||||
fv.InvalidDevices = append(fv.InvalidDevices, device)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
existingDevice, _ := vl.RawVersions[i].FirstDevice()
|
||||
insert, err := shouldInsertBefore(ordering, folder, existingDevice, vl.RawVersions[i].IsInvalid(), file, t)
|
||||
existingDevice, _ := fvFirstDevice(fv)
|
||||
insert, err := shouldInsertBefore(ordering, folder, existingDevice, fvIsInvalid(fv), file, t)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if insert {
|
||||
vl.insertAt(i, newFileVersion(device, file.FileVersion(), file.IsInvalid(), file.IsDeleted()))
|
||||
vlInsertAt(vl, i, newFileVersion(device, file.FileVersion(), file.IsInvalid(), file.IsDeleted()))
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
@@ -435,7 +281,7 @@ func (vl *VersionList) checkInsertAt(i int, folder, device []byte, file protocol
|
||||
// shouldInsertBefore determines whether the file comes before an existing
|
||||
// entry, given the version ordering (existing compared to new one), existing
|
||||
// device and if the existing version is invalid.
|
||||
func shouldInsertBefore(ordering protocol.Ordering, folder, existingDevice []byte, existingInvalid bool, file protocol.FileIntf, t readOnlyTransaction) (bool, error) {
|
||||
func shouldInsertBefore(ordering protocol.Ordering, folder, existingDevice []byte, existingInvalid bool, file protocol.FileInfo, t readOnlyTransaction) (bool, error) {
|
||||
switch ordering {
|
||||
case protocol.Lesser:
|
||||
// The version at this point in the list is lesser
|
||||
@@ -461,10 +307,7 @@ func shouldInsertBefore(ordering protocol.Ordering, folder, existingDevice []byt
|
||||
if !ok {
|
||||
return true, nil
|
||||
}
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if protocol.WinsConflict(file, of) {
|
||||
if file.WinsConflict(of) {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
@@ -484,9 +327,9 @@ func popDeviceAt(devices [][]byte, i int) [][]byte {
|
||||
return append(devices[:i], devices[i+1:]...)
|
||||
}
|
||||
|
||||
func newFileVersion(device []byte, version protocol.Vector, invalid, deleted bool) FileVersion {
|
||||
fv := FileVersion{
|
||||
Version: version,
|
||||
func newFileVersion(device []byte, version protocol.Vector, invalid, deleted bool) *dbproto.FileVersion {
|
||||
fv := &dbproto.FileVersion{
|
||||
Version: version.ToWire(),
|
||||
Deleted: deleted,
|
||||
}
|
||||
if invalid {
|
||||
@@ -497,7 +340,7 @@ func newFileVersion(device []byte, version protocol.Vector, invalid, deleted boo
|
||||
return fv
|
||||
}
|
||||
|
||||
func (fv FileVersion) FirstDevice() ([]byte, bool) {
|
||||
func fvFirstDevice(fv *dbproto.FileVersion) ([]byte, bool) {
|
||||
if len(fv.Devices) != 0 {
|
||||
return fv.Devices[0], true
|
||||
}
|
||||
@@ -507,18 +350,14 @@ func (fv FileVersion) FirstDevice() ([]byte, bool) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (fv FileVersion) IsInvalid() bool {
|
||||
return len(fv.Devices) == 0
|
||||
func fvIsInvalid(fv *dbproto.FileVersion) bool {
|
||||
return fv == nil || len(fv.Devices) == 0
|
||||
}
|
||||
|
||||
func (fv FileVersion) deviceCount() int {
|
||||
func fvDeviceCount(fv *dbproto.FileVersion) int {
|
||||
return len(fv.Devices) + len(fv.InvalidDevices)
|
||||
}
|
||||
|
||||
func (fv FileVersion) copy() FileVersion {
|
||||
n := fv
|
||||
n.Version = fv.Version.Copy()
|
||||
n.Devices = append([][]byte{}, fv.Devices...)
|
||||
n.InvalidDevices = append([][]byte{}, fv.InvalidDevices...)
|
||||
return n
|
||||
func fvCopy(fv *dbproto.FileVersion) *dbproto.FileVersion {
|
||||
return proto.Clone(fv).(*dbproto.FileVersion)
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1 +0,0 @@
|
||||
index.db
|
||||
-22
@@ -1,22 +0,0 @@
|
||||
{"k":"AAAAAAAAAAABL25vdGdvb2Q=","v":"Cggvbm90Z29vZEoHCgUIARDoB1ACggEiGiAAAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHw=="}
|
||||
{"k":"AAAAAAAAAAABYQ==","v":"CgFhSgcKBQgBEOgHUAGCASIaIAABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4f"}
|
||||
{"k":"AAAAAAAAAAACYg==","v":"CgFiSgcKBQgBEOkHggEiGiAAAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eH4IBJBABGiABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fIA=="}
|
||||
{"k":"AAAAAAAAAAACYw==","v":"CgFjOAFKBwoFCAEQ6geCASIaIAABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fggEkEAEaIAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gggEkEAIaIAIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyAhggEkEAMaIAMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fICEiggEkEAQaIAQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIj"}
|
||||
{"k":"AAAAAAAAAAACZA==","v":"CgFkSgcKBQgBEOsHggEiGiAAAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eH4IBJBABGiABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fIIIBJBACGiACAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gIYIBJBADGiADBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyAhIoIBJBAEGiAEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fICEiI4IBJBAFGiAFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJIIBJBAGGiAGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyAhIiMkJQ=="}
|
||||
{"k":"AAAAAAAAAAADYw==","v":"CgFjSgcKBQgBEOoHggEiGiAAAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eH4IBJBABGiABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fIIIBJBACGiACAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gIYIBJBADGiADBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyAhIoIBJBAEGiAEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fICEiI4IBJBAFGiAFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJIIBJBAGGiAGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyAhIiMkJQ=="}
|
||||
{"k":"AAAAAAAAAAADZA==","v":"CgFkOAFKBwoFCAEQ6weCASIaIAABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fggEkEAEaIAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gggEkEAIaIAIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyAhggEkEAMaIAMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fICEiggEkEAQaIAQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIj"}
|
||||
{"k":"AAAAAAAAAAADaW52YWxpZA==","v":"CgdpbnZhbGlkOAFKBwoFCAEQ7AeCASIaIAABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fggEkEAEaIAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gggEkEAIaIAIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyAhggEkEAMaIAMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fICEiggEkEAQaIAQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIj"}
|
||||
{"k":"AQAAAAAvbm90Z29vZA==","v":"CisKBwoFCAEQ6AcSIP//////////////////////////////////////////"}
|
||||
{"k":"AQAAAABh","v":"CisKBwoFCAEQ6AcSIP//////////////////////////////////////////"}
|
||||
{"k":"AQAAAABi","v":"CisKBwoFCAEQ6QcSIAIj5b8/Vx850vCTKUE+HcWcQZUIgmhv//rEL3j3A/At"}
|
||||
{"k":"AQAAAABj","v":"CisKBwoFCAEQ6gcSIEeUA//e9Ja19eW8nAoVIh5wBzFkUJ+jB2GvYwlPb5RcCi0KBwoFCAEQ6gcSIAIj5b8/Vx850vCTKUE+HcWcQZUIgmhv//rEL3j3A/AtGAE="}
|
||||
{"k":"AQAAAABk","v":"CisKBwoFCAEQ6wcSIAIj5b8/Vx850vCTKUE+HcWcQZUIgmhv//rEL3j3A/AtCi0KBwoFCAEQ6wcSIEeUA//e9Ja19eW8nAoVIh5wBzFkUJ+jB2GvYwlPb5RcGAE="}
|
||||
{"k":"AQAAAABpbnZhbGlk","v":"Ci0KBwoFCAEQ7AcSIEeUA//e9Ja19eW8nAoVIh5wBzFkUJ+jB2GvYwlPb5RcGAE="}
|
||||
{"k":"AgAAAAAAAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHy9ub3Rnb29k","v":"AAAAAA=="}
|
||||
{"k":"AgAAAAAAAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eH2E=","v":"AAAAAA=="}
|
||||
{"k":"BgAAAAAAAAAA","v":"VXBkYXRlU2NoZW1hMHRvMw=="}
|
||||
{"k":"BwAAAAAAAAAA","v":""}
|
||||
{"k":"BwAAAAEAAAAA","v":"//////////////////////////////////////////8="}
|
||||
{"k":"BwAAAAIAAAAA","v":"AiPlvz9XHznS8JMpQT4dxZxBlQiCaG//+sQvePcD8C0="}
|
||||
{"k":"BwAAAAMAAAAA","v":"R5QD/970lrX15bycChUiHnAHMWRQn6MHYa9jCU9vlFw="}
|
||||
{"k":"CQAAAAA=","v":"CicIAjACigEg//////////////////////////////////////////8KJwgFMAKKASD4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+AolCAKKASACI+W/P1cfOdLwkylBPh3FnEGVCIJob//6xC949wPwLQolCAGKASBHlAP/3vSWtfXlvJwKFSIecAcxZFCfowdhr2MJT2+UXBCyn6iaw4HGlxU="}
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
{"k":"AAAAAAAAAAABYmFy","v":"CgNiYXJKBwoFCAEQ6QdQAg=="}
|
||||
{"k":"AAAAAAAAAAABZm9v","v":"CgNmb284AUoHCgUIARDoB1AB"}
|
||||
{"k":"AAAAAAAAAAACYmF6","v":"CgNiYXo4AUoHCgUIKhDoBw=="}
|
||||
{"k":"AAAAAAAAAAACcXV1eA==","v":"CgRxdXV4SgcKBQgqEOoH"}
|
||||
{"k":"AQAAAABiYXI=","v":"CisKBwoFCAEQ6QcSIP//////////////////////////////////////////"}
|
||||
{"k":"AQAAAABiYXo=","v":"Ci0KBwoFCCoQ6AcSICoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAE="}
|
||||
{"k":"AQAAAABmb28=","v":"Ci0KBwoFCAEQ6AcSIP//////////////////////////////////////////GAE="}
|
||||
{"k":"AQAAAABxdXV4","v":"CisKBwoFCCoQ6gcSICoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"}
|
||||
{"k":"BgAAAAAAAAAA","v":"dGVzdA=="}
|
||||
{"k":"BwAAAAAAAAAA","v":""}
|
||||
{"k":"BwAAAAEAAAAA","v":"//////////////////////////////////////////8="}
|
||||
{"k":"BwAAAAIAAAAA","v":"KgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="}
|
||||
{"k":"CQAAAAA=","v":"CicIATACigEg//////////////////////////////////////////8KJwgCMAKKASD4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+AolCAGKASAqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCoudnCuM+vlxU="}
|
||||
{"k":"CwAAAAAAAAAAAAAAAQ==","v":"AAAAAAAAAAABZm9v"}
|
||||
{"k":"CwAAAAAAAAAAAAAAAg==","v":"AAAAAAAAAAABYmFy"}
|
||||
-24
@@ -1,24 +0,0 @@
|
||||
{"k":"AAAAAAAAAAABYQ==","v":"CgFhMAFKBwoFCAEQ6AdQAQ=="}
|
||||
{"k":"AAAAAAAAAAABYg==","v":"CgFiSgcKBQgBEOgHUAKCASIaIAABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fggEkEAEaIAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gkgEgC8XkepY1E4woWwAAyi81YItXr5CMuwY6mfvf2iLupTo="}
|
||||
{"k":"AAAAAAAAAAABYw==","v":"CgFjMAFKBwoFCAEQ6AdQAw=="}
|
||||
{"k":"AAAAAAAAAAACYQ==","v":"CgFhMAFKBwoFCAEQ6AdQAQ=="}
|
||||
{"k":"AAAAAAAAAAACYg==","v":"CgFiMAFKFQoFCAEQ6AcKDAi5vtz687f5kQIQAVACggEiGiAAAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eH4IBJBABGiABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fIJIBIAvF5HqWNROMKFsAAMovNWCLV6+QjLsGOpn739oi7qU6"}
|
||||
{"k":"AAAAAAAAAAACYw==","v":"CgFjShUKBQgBEOgHCgwIub7c+vO3+ZECEAFQA4IBIhogAAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh+SASBjDc0pZsQzZpESVEi7sltP9BKknHMtssirwbhYG9cQ3Q=="}
|
||||
{"k":"AQAAAABh","v":"CisKBwoFCAEQ6AcSIAIj5b8/Vx850vCTKUE+HcWcQZUIgmhv//rEL3j3A/AtCisKBwoFCAEQ6AcSIP//////////////////////////////////////////"}
|
||||
{"k":"AQAAAABi","v":"CjkKFQoFCAEQ6AcKDAi5vtz687f5kQIQARIgAiPlvz9XHznS8JMpQT4dxZxBlQiCaG//+sQvePcD8C0KKwoHCgUIARDoBxIg//////////////////////////////////////////8="}
|
||||
{"k":"AQAAAABj","v":"CjkKFQoFCAEQ6AcKDAi5vtz687f5kQIQARIgAiPlvz9XHznS8JMpQT4dxZxBlQiCaG//+sQvePcD8C0KKwoHCgUIARDoBxIg//////////////////////////////////////////8="}
|
||||
{"k":"AgAAAAAAAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eH2I=","v":"AAAAAA=="}
|
||||
{"k":"AgAAAAABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fIGI=","v":"AAAAAQ=="}
|
||||
{"k":"BgAAAAAAAAAA","v":"dGVzdA=="}
|
||||
{"k":"BwAAAAAAAAAA","v":""}
|
||||
{"k":"BwAAAAEAAAAA","v":"//////////////////////////////////////////8="}
|
||||
{"k":"BwAAAAIAAAAA","v":"AiPlvz9XHznS8JMpQT4dxZxBlQiCaG//+sQvePcD8C0="}
|
||||
{"k":"CQAAAAA=","v":"CikIASACMAOKASD//////////////////////////////////////////wonCAEgAooBIPj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4CikIASACMAOKASACI+W/P1cfOdLwkylBPh3FnEGVCIJob//6xC949wPwLRDE7Jrik+mdhhY="}
|
||||
{"k":"CmRiTWluU3luY3RoaW5nVmVyc2lvbg==","v":"djEuNC4w"}
|
||||
{"k":"CmRiVmVyc2lvbg==","v":"AAAAAAAAAAk="}
|
||||
{"k":"Cmxhc3RJbmRpcmVjdEdDVGltZQ==","v":"AAAAAF6yy/Q="}
|
||||
{"k":"CwAAAAAAAAAAAAAAAQ==","v":"AAAAAAAAAAABYQ=="}
|
||||
{"k":"CwAAAAAAAAAAAAAAAg==","v":"AAAAAAAAAAABYg=="}
|
||||
{"k":"CwAAAAAAAAAAAAAAAw==","v":"AAAAAAAAAAABYw=="}
|
||||
{"k":"DAAAAABi","v":""}
|
||||
{"k":"DAAAAABj","v":""}
|
||||
+112
-105
@@ -11,10 +11,15 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
"github.com/syncthing/syncthing/internal/gen/bep"
|
||||
"github.com/syncthing/syncthing/internal/gen/dbproto"
|
||||
"github.com/syncthing/syncthing/lib/db/backend"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
"github.com/syncthing/syncthing/lib/osutil"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
"github.com/syncthing/syncthing/lib/sliceutil"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -63,48 +68,49 @@ func (t readOnlyTransaction) getFileByKey(key []byte) (protocol.FileInfo, bool,
|
||||
if err != nil || !ok {
|
||||
return protocol.FileInfo{}, false, err
|
||||
}
|
||||
return f.(protocol.FileInfo), true, nil
|
||||
return f, true, nil
|
||||
}
|
||||
|
||||
func (t readOnlyTransaction) getFileTrunc(key []byte, trunc bool) (protocol.FileIntf, bool, error) {
|
||||
func (t readOnlyTransaction) getFileTrunc(key []byte, trunc bool) (protocol.FileInfo, bool, error) {
|
||||
bs, err := t.Get(key)
|
||||
if backend.IsNotFound(err) {
|
||||
return nil, false, nil
|
||||
return protocol.FileInfo{}, false, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
return protocol.FileInfo{}, false, err
|
||||
}
|
||||
f, err := t.unmarshalTrunc(bs, trunc)
|
||||
if backend.IsNotFound(err) {
|
||||
return nil, false, nil
|
||||
return protocol.FileInfo{}, false, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
return protocol.FileInfo{}, false, err
|
||||
}
|
||||
return f, true, nil
|
||||
}
|
||||
|
||||
func (t readOnlyTransaction) unmarshalTrunc(bs []byte, trunc bool) (protocol.FileIntf, error) {
|
||||
func (t readOnlyTransaction) unmarshalTrunc(bs []byte, trunc bool) (protocol.FileInfo, error) {
|
||||
if trunc {
|
||||
var tf FileInfoTruncated
|
||||
err := tf.Unmarshal(bs)
|
||||
var bfi dbproto.FileInfoTruncated
|
||||
err := proto.Unmarshal(bs, &bfi)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return protocol.FileInfo{}, err
|
||||
}
|
||||
if err := t.fillTruncated(&tf); err != nil {
|
||||
return nil, err
|
||||
if err := t.fillTruncated(&bfi); err != nil {
|
||||
return protocol.FileInfo{}, err
|
||||
}
|
||||
return tf, nil
|
||||
return protocol.FileInfoFromDBTruncated(&bfi), nil
|
||||
}
|
||||
|
||||
var fi protocol.FileInfo
|
||||
if err := fi.Unmarshal(bs); err != nil {
|
||||
return nil, err
|
||||
var bfi bep.FileInfo
|
||||
err := proto.Unmarshal(bs, &bfi)
|
||||
if err != nil {
|
||||
return protocol.FileInfo{}, err
|
||||
}
|
||||
if err := t.fillFileInfo(&fi); err != nil {
|
||||
return nil, err
|
||||
if err := t.fillFileInfo(&bfi); err != nil {
|
||||
return protocol.FileInfo{}, err
|
||||
}
|
||||
return fi, nil
|
||||
return protocol.FileInfoFromDB(&bfi), nil
|
||||
}
|
||||
|
||||
type blocksIndirectionError struct {
|
||||
@@ -121,7 +127,7 @@ func (e *blocksIndirectionError) Unwrap() error {
|
||||
|
||||
// fillFileInfo follows the (possible) indirection of blocks and version
|
||||
// vector and fills it out.
|
||||
func (t readOnlyTransaction) fillFileInfo(fi *protocol.FileInfo) error {
|
||||
func (t readOnlyTransaction) fillFileInfo(fi *bep.FileInfo) error {
|
||||
var key []byte
|
||||
|
||||
if len(fi.Blocks) == 0 && len(fi.BlocksHash) != 0 {
|
||||
@@ -131,8 +137,8 @@ func (t readOnlyTransaction) fillFileInfo(fi *protocol.FileInfo) error {
|
||||
if err != nil {
|
||||
return &blocksIndirectionError{err}
|
||||
}
|
||||
var bl BlockList
|
||||
if err := bl.Unmarshal(bs); err != nil {
|
||||
var bl dbproto.BlockList
|
||||
if err := proto.Unmarshal(bs, &bl); err != nil {
|
||||
return err
|
||||
}
|
||||
fi.Blocks = bl.Blocks
|
||||
@@ -144,11 +150,11 @@ func (t readOnlyTransaction) fillFileInfo(fi *protocol.FileInfo) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("filling Version: %w", err)
|
||||
}
|
||||
var v protocol.Vector
|
||||
if err := v.Unmarshal(bs); err != nil {
|
||||
var v bep.Vector
|
||||
if err := proto.Unmarshal(bs, &v); err != nil {
|
||||
return err
|
||||
}
|
||||
fi.Version = v
|
||||
fi.Version = &v
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -156,7 +162,7 @@ func (t readOnlyTransaction) fillFileInfo(fi *protocol.FileInfo) error {
|
||||
|
||||
// fillTruncated follows the (possible) indirection of version vector and
|
||||
// fills it.
|
||||
func (t readOnlyTransaction) fillTruncated(fi *FileInfoTruncated) error {
|
||||
func (t readOnlyTransaction) fillTruncated(fi *dbproto.FileInfoTruncated) error {
|
||||
var key []byte
|
||||
|
||||
if len(fi.VersionHash) == 0 {
|
||||
@@ -168,73 +174,72 @@ func (t readOnlyTransaction) fillTruncated(fi *FileInfoTruncated) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var v protocol.Vector
|
||||
if err := v.Unmarshal(bs); err != nil {
|
||||
var v bep.Vector
|
||||
if err := proto.Unmarshal(bs, &v); err != nil {
|
||||
return err
|
||||
}
|
||||
fi.Version = v
|
||||
fi.Version = &v
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t readOnlyTransaction) getGlobalVersions(keyBuf, folder, file []byte) (VersionList, error) {
|
||||
func (t readOnlyTransaction) getGlobalVersions(keyBuf, folder, file []byte) (*dbproto.VersionList, error) {
|
||||
var err error
|
||||
keyBuf, err = t.keyer.GenerateGlobalVersionKey(keyBuf, folder, file)
|
||||
if err != nil {
|
||||
return VersionList{}, err
|
||||
return nil, err
|
||||
}
|
||||
return t.getGlobalVersionsByKey(keyBuf)
|
||||
}
|
||||
|
||||
func (t readOnlyTransaction) getGlobalVersionsByKey(key []byte) (VersionList, error) {
|
||||
func (t readOnlyTransaction) getGlobalVersionsByKey(key []byte) (*dbproto.VersionList, error) {
|
||||
bs, err := t.Get(key)
|
||||
if err != nil {
|
||||
return VersionList{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var vl VersionList
|
||||
if err := vl.Unmarshal(bs); err != nil {
|
||||
return VersionList{}, err
|
||||
var vl dbproto.VersionList
|
||||
if err := proto.Unmarshal(bs, &vl); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return vl, nil
|
||||
return &vl, nil
|
||||
}
|
||||
|
||||
func (t readOnlyTransaction) getGlobal(keyBuf, folder, file []byte, truncate bool) ([]byte, protocol.FileIntf, bool, error) {
|
||||
func (t readOnlyTransaction) getGlobal(keyBuf, folder, file []byte, truncate bool) ([]byte, protocol.FileInfo, bool, error) {
|
||||
vl, err := t.getGlobalVersions(keyBuf, folder, file)
|
||||
if backend.IsNotFound(err) {
|
||||
return keyBuf, nil, false, nil
|
||||
return keyBuf, protocol.FileInfo{}, false, nil
|
||||
} else if err != nil {
|
||||
return nil, nil, false, err
|
||||
return nil, protocol.FileInfo{}, false, err
|
||||
}
|
||||
var fi protocol.FileIntf
|
||||
keyBuf, fi, err = t.getGlobalFromVersionList(keyBuf, folder, file, truncate, vl)
|
||||
keyBuf, fi, err := t.getGlobalFromVersionList(keyBuf, folder, file, truncate, vl)
|
||||
return keyBuf, fi, true, err
|
||||
}
|
||||
|
||||
func (t readOnlyTransaction) getGlobalFromVersionList(keyBuf, folder, file []byte, truncate bool, vl VersionList) ([]byte, protocol.FileIntf, error) {
|
||||
fv, ok := vl.GetGlobal()
|
||||
func (t readOnlyTransaction) getGlobalFromVersionList(keyBuf, folder, file []byte, truncate bool, vl *dbproto.VersionList) ([]byte, protocol.FileInfo, error) {
|
||||
fv, ok := vlGetGlobal(vl)
|
||||
if !ok {
|
||||
return keyBuf, nil, errEmptyGlobal
|
||||
return keyBuf, protocol.FileInfo{}, errEmptyGlobal
|
||||
}
|
||||
keyBuf, fi, err := t.getGlobalFromFileVersion(keyBuf, folder, file, truncate, fv)
|
||||
return keyBuf, fi, err
|
||||
}
|
||||
|
||||
func (t readOnlyTransaction) getGlobalFromFileVersion(keyBuf, folder, file []byte, truncate bool, fv FileVersion) ([]byte, protocol.FileIntf, error) {
|
||||
dev, ok := fv.FirstDevice()
|
||||
func (t readOnlyTransaction) getGlobalFromFileVersion(keyBuf, folder, file []byte, truncate bool, fv *dbproto.FileVersion) ([]byte, protocol.FileInfo, error) {
|
||||
dev, ok := fvFirstDevice(fv)
|
||||
if !ok {
|
||||
return keyBuf, nil, errEmptyFileVersion
|
||||
return keyBuf, protocol.FileInfo{}, errEmptyFileVersion
|
||||
}
|
||||
keyBuf, err := t.keyer.GenerateDeviceFileKey(keyBuf, folder, dev, file)
|
||||
if err != nil {
|
||||
return keyBuf, nil, err
|
||||
return keyBuf, protocol.FileInfo{}, err
|
||||
}
|
||||
fi, ok, err := t.getFileTrunc(keyBuf, truncate)
|
||||
if err != nil {
|
||||
return keyBuf, nil, err
|
||||
return keyBuf, protocol.FileInfo{}, err
|
||||
}
|
||||
if !ok {
|
||||
return keyBuf, nil, errEntryFromGlobalMissing
|
||||
return keyBuf, protocol.FileInfo{}, errEntryFromGlobalMissing
|
||||
}
|
||||
return keyBuf, fi, nil
|
||||
}
|
||||
@@ -357,13 +362,13 @@ func (t *readOnlyTransaction) withGlobal(folder, prefix []byte, truncate bool, f
|
||||
return nil
|
||||
}
|
||||
|
||||
var vl VersionList
|
||||
if err := vl.Unmarshal(dbi.Value()); err != nil {
|
||||
var vl dbproto.VersionList
|
||||
if err := proto.Unmarshal(dbi.Value(), &vl); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var f protocol.FileIntf
|
||||
dk, f, err = t.getGlobalFromVersionList(dk, folder, name, truncate, vl)
|
||||
var f protocol.FileInfo
|
||||
dk, f, err = t.getGlobalFromVersionList(dk, folder, name, truncate, &vl)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -432,7 +437,7 @@ func (t *readOnlyTransaction) availability(folder, file []byte) ([]protocol.Devi
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fv, ok := vl.GetGlobal()
|
||||
fv, ok := vlGetGlobal(vl)
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -472,32 +477,32 @@ func (t *readOnlyTransaction) withNeedIteratingGlobal(folder, device []byte, tru
|
||||
return err
|
||||
}
|
||||
for dbi.Next() {
|
||||
var vl VersionList
|
||||
if err := vl.Unmarshal(dbi.Value()); err != nil {
|
||||
var vl dbproto.VersionList
|
||||
if err := proto.Unmarshal(dbi.Value(), &vl); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
globalFV, ok := vl.GetGlobal()
|
||||
globalFV, ok := vlGetGlobal(&vl)
|
||||
if !ok {
|
||||
return errEmptyGlobal
|
||||
}
|
||||
haveFV, have := vl.Get(device)
|
||||
haveFV, have := vlGet(&vl, device)
|
||||
|
||||
if !Need(globalFV, have, haveFV.Version) {
|
||||
if !Need(globalFV, have, protocol.VectorFromWire(haveFV.Version)) {
|
||||
continue
|
||||
}
|
||||
|
||||
name := t.keyer.NameFromGlobalVersionKey(dbi.Key())
|
||||
var gf protocol.FileIntf
|
||||
var gf protocol.FileInfo
|
||||
dk, gf, err = t.getGlobalFromFileVersion(dk, folder, name, truncate, globalFV)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if shouldDebug() {
|
||||
if globalDev, ok := globalFV.FirstDevice(); ok {
|
||||
if globalDev, ok := fvFirstDevice(globalFV); ok {
|
||||
globalID, _ := protocol.DeviceIDFromBytes(globalDev)
|
||||
l.Debugf("need folder=%q device=%v name=%q have=%v invalid=%v haveV=%v haveDeleted=%v globalV=%v globalDeleted=%v globalDev=%v", folder, devID, name, have, haveFV.IsInvalid(), haveFV.Version, haveFV.Deleted, gf.FileVersion(), globalFV.Deleted, globalID)
|
||||
l.Debugf("need folder=%q device=%v name=%q have=%v invalid=%v haveV=%v haveDeleted=%v globalV=%v globalDeleted=%v globalDev=%v", folder, devID, name, have, fvIsInvalid(haveFV), haveFV.Version, haveFV.Deleted, gf.FileVersion(), globalFV.Deleted, globalID)
|
||||
}
|
||||
}
|
||||
if !fn(gf) {
|
||||
@@ -519,7 +524,7 @@ func (t *readOnlyTransaction) withNeedLocal(folder []byte, truncate bool, fn Ite
|
||||
defer dbi.Release()
|
||||
|
||||
var keyBuf []byte
|
||||
var f protocol.FileIntf
|
||||
var f protocol.FileInfo
|
||||
var ok bool
|
||||
for dbi.Next() {
|
||||
keyBuf, f, ok, err = t.getGlobal(keyBuf, folder, t.keyer.NameFromGlobalVersionKey(dbi.Key()), truncate)
|
||||
@@ -589,7 +594,8 @@ func (t readWriteTransaction) putFile(fkey []byte, fi protocol.FileInfo) error {
|
||||
bkey = t.keyer.GenerateBlockListKey(bkey, fi.BlocksHash)
|
||||
if _, err := t.Get(bkey); backend.IsNotFound(err) {
|
||||
// Marshal the block list and save it
|
||||
blocksBs := mustMarshal(&BlockList{Blocks: fi.Blocks})
|
||||
blocks := sliceutil.Map(fi.Blocks, protocol.BlockInfo.ToWire)
|
||||
blocksBs := mustMarshal(&dbproto.BlockList{Blocks: blocks})
|
||||
if err := t.Put(bkey, blocksBs); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -605,7 +611,7 @@ func (t readWriteTransaction) putFile(fkey []byte, fi protocol.FileInfo) error {
|
||||
bkey = t.keyer.GenerateVersionKey(bkey, fi.VersionHash)
|
||||
if _, err := t.Get(bkey); backend.IsNotFound(err) {
|
||||
// Marshal the version vector and save it
|
||||
versionBs := mustMarshal(&fi.Version)
|
||||
versionBs := mustMarshal(fi.Version.ToWire())
|
||||
if err := t.Put(bkey, versionBs); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -619,7 +625,7 @@ func (t readWriteTransaction) putFile(fkey []byte, fi protocol.FileInfo) error {
|
||||
|
||||
t.indirectionTracker.recordIndirectionHashesForFile(&fi)
|
||||
|
||||
fiBs := mustMarshal(&fi)
|
||||
fiBs := mustMarshal(fi.ToWire(true))
|
||||
return t.Put(fkey, fiBs)
|
||||
}
|
||||
|
||||
@@ -638,8 +644,11 @@ func (t readWriteTransaction) updateGlobal(gk, keyBuf, folder, device []byte, fi
|
||||
if err != nil && !backend.IsNotFound(err) {
|
||||
return nil, err
|
||||
}
|
||||
if fl == nil {
|
||||
fl = &dbproto.VersionList{}
|
||||
}
|
||||
|
||||
globalFV, oldGlobalFV, removedFV, haveOldGlobal, haveRemoved, globalChanged, err := fl.update(folder, device, file, t.readOnlyTransaction)
|
||||
globalFV, oldGlobalFV, removedFV, haveOldGlobal, haveRemoved, globalChanged, err := vlUpdate(fl, folder, device, file, t.readOnlyTransaction)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -647,20 +656,20 @@ func (t readWriteTransaction) updateGlobal(gk, keyBuf, folder, device []byte, fi
|
||||
name := []byte(file.Name)
|
||||
|
||||
l.Debugf(`new global for "%v" after update: %v`, file.Name, fl)
|
||||
if err := t.Put(gk, mustMarshal(&fl)); err != nil {
|
||||
if err := t.Put(gk, mustMarshal(fl)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Only load those from db if actually needed
|
||||
|
||||
var gotGlobal, gotOldGlobal bool
|
||||
var global, oldGlobal protocol.FileIntf
|
||||
var global, oldGlobal protocol.FileInfo
|
||||
|
||||
// Check the need of the device that was updated
|
||||
// Must happen before updating global meta: If this is the first
|
||||
// item from this device, it will be initialized with the global state.
|
||||
|
||||
needBefore := haveOldGlobal && Need(oldGlobalFV, haveRemoved, removedFV.Version)
|
||||
needBefore := haveOldGlobal && Need(oldGlobalFV, haveRemoved, protocol.VectorFromWire(removedFV.GetVersion()))
|
||||
needNow := Need(globalFV, true, file.Version)
|
||||
if needBefore {
|
||||
if keyBuf, oldGlobal, err = t.getGlobalFromFileVersion(keyBuf, folder, name, true, oldGlobalFV); err != nil {
|
||||
@@ -709,7 +718,7 @@ func (t readWriteTransaction) updateGlobal(gk, keyBuf, folder, device []byte, fi
|
||||
|
||||
// Add the new global to the global size counter
|
||||
if !gotGlobal {
|
||||
if globalFV.Version.Equal(file.Version) {
|
||||
if protocol.VectorFromWire(globalFV.Version).Equal(file.Version) {
|
||||
// The inserted file is the global file
|
||||
global = file
|
||||
} else {
|
||||
@@ -718,15 +727,15 @@ func (t readWriteTransaction) updateGlobal(gk, keyBuf, folder, device []byte, fi
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
gotGlobal = true
|
||||
}
|
||||
meta.addFile(protocol.GlobalDeviceID, global)
|
||||
|
||||
// check for local (if not already done before)
|
||||
if !bytes.Equal(device, protocol.LocalDeviceID[:]) {
|
||||
localFV, haveLocal := fl.Get(protocol.LocalDeviceID[:])
|
||||
needBefore := haveOldGlobal && Need(oldGlobalFV, haveLocal, localFV.Version)
|
||||
needNow := Need(globalFV, haveLocal, localFV.Version)
|
||||
localFV, haveLocal := vlGet(fl, protocol.LocalDeviceID[:])
|
||||
localVersion := protocol.VectorFromWire(localFV.Version)
|
||||
needBefore := haveOldGlobal && Need(oldGlobalFV, haveLocal, localVersion)
|
||||
needNow := Need(globalFV, haveLocal, localVersion)
|
||||
if needBefore {
|
||||
meta.removeNeeded(protocol.LocalDeviceID, oldGlobal)
|
||||
if !needNow {
|
||||
@@ -750,11 +759,12 @@ func (t readWriteTransaction) updateGlobal(gk, keyBuf, folder, device []byte, fi
|
||||
// Already handled above
|
||||
continue
|
||||
}
|
||||
fv, have := fl.Get(dev[:])
|
||||
if haveOldGlobal && Need(oldGlobalFV, have, fv.Version) {
|
||||
fv, have := vlGet(fl, dev[:])
|
||||
fvVersion := protocol.VectorFromWire(fv.Version)
|
||||
if haveOldGlobal && Need(oldGlobalFV, have, fvVersion) {
|
||||
meta.removeNeeded(dev, oldGlobal)
|
||||
}
|
||||
if Need(globalFV, have, fv.Version) {
|
||||
if Need(globalFV, have, fvVersion) {
|
||||
meta.addNeeded(dev, global)
|
||||
}
|
||||
}
|
||||
@@ -778,11 +788,12 @@ func (t readWriteTransaction) updateLocalNeed(keyBuf, folder, name []byte, add b
|
||||
return keyBuf, err
|
||||
}
|
||||
|
||||
func Need(global FileVersion, haveLocal bool, localVersion protocol.Vector) bool {
|
||||
func Need(global *dbproto.FileVersion, haveLocal bool, localVersion protocol.Vector) bool {
|
||||
// We never need an invalid file or a file without a valid version (just
|
||||
// another way of expressing "invalid", really, until we fix that
|
||||
// part...).
|
||||
if global.IsInvalid() || global.Version.IsEmpty() {
|
||||
globalVersion := protocol.VectorFromWire(global.Version)
|
||||
if fvIsInvalid(global) || globalVersion.IsEmpty() {
|
||||
return false
|
||||
}
|
||||
// We don't need a deleted file if we don't have it.
|
||||
@@ -790,7 +801,7 @@ func Need(global FileVersion, haveLocal bool, localVersion protocol.Vector) bool
|
||||
return false
|
||||
}
|
||||
// We don't need the global file if we already have the same version.
|
||||
if haveLocal && localVersion.GreaterEqual(global.Version) {
|
||||
if haveLocal && localVersion.GreaterEqual(globalVersion) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
@@ -816,8 +827,8 @@ func (t readWriteTransaction) removeFromGlobal(gk, keyBuf, folder, device, file
|
||||
return nil, err
|
||||
}
|
||||
|
||||
oldGlobalFV, haveOldGlobal := fl.GetGlobal()
|
||||
oldGlobalFV = oldGlobalFV.copy()
|
||||
oldGlobalFV, haveOldGlobal := vlGetGlobal(fl)
|
||||
oldGlobalFV = fvCopy(oldGlobalFV)
|
||||
|
||||
if !haveOldGlobal {
|
||||
// Shouldn't ever happen, but doesn't hurt to handle.
|
||||
@@ -825,18 +836,18 @@ func (t readWriteTransaction) removeFromGlobal(gk, keyBuf, folder, device, file
|
||||
return keyBuf, t.Delete(gk)
|
||||
}
|
||||
|
||||
removedFV, haveRemoved, globalChanged := fl.pop(device)
|
||||
removedFV, haveRemoved, globalChanged := vlPop(fl, device)
|
||||
if !haveRemoved {
|
||||
// There is no version for the given device
|
||||
return keyBuf, nil
|
||||
}
|
||||
|
||||
var global protocol.FileIntf
|
||||
var global protocol.FileInfo
|
||||
var gotGlobal bool
|
||||
|
||||
globalFV, haveGlobal := fl.GetGlobal()
|
||||
globalFV, haveGlobal := vlGetGlobal(fl)
|
||||
// Add potential needs of the removed device
|
||||
if haveGlobal && !globalFV.IsInvalid() && Need(globalFV, false, protocol.Vector{}) && !Need(oldGlobalFV, haveRemoved, removedFV.Version) {
|
||||
if haveGlobal && !fvIsInvalid(globalFV) && Need(globalFV, false, protocol.Vector{}) && !Need(oldGlobalFV, haveRemoved, protocol.VectorFromWire(removedFV.Version)) {
|
||||
keyBuf, global, err = t.getGlobalFromVersionList(keyBuf, folder, file, true, fl)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -853,13 +864,13 @@ func (t readWriteTransaction) removeFromGlobal(gk, keyBuf, folder, device, file
|
||||
// Global hasn't changed, abort early
|
||||
if !globalChanged {
|
||||
l.Debugf("new global after remove: %v", fl)
|
||||
if err := t.Put(gk, mustMarshal(&fl)); err != nil {
|
||||
if err := t.Put(gk, mustMarshal(fl)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return keyBuf, nil
|
||||
}
|
||||
|
||||
var oldGlobal protocol.FileIntf
|
||||
var oldGlobal protocol.FileInfo
|
||||
keyBuf, oldGlobal, err = t.getGlobalFromFileVersion(keyBuf, folder, file, true, oldGlobalFV)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -868,11 +879,12 @@ func (t readWriteTransaction) removeFromGlobal(gk, keyBuf, folder, device, file
|
||||
|
||||
// Remove potential device needs
|
||||
shouldRemoveNeed := func(dev protocol.DeviceID) bool {
|
||||
fv, have := fl.Get(dev[:])
|
||||
if !Need(oldGlobalFV, have, fv.Version) {
|
||||
fv, have := vlGet(fl, dev[:])
|
||||
fvVersion := protocol.VectorFromWire(fv.Version)
|
||||
if !Need(oldGlobalFV, have, fvVersion) {
|
||||
return false // Didn't need it before
|
||||
}
|
||||
return !haveGlobal || !Need(globalFV, have, fv.Version)
|
||||
return !haveGlobal || !Need(globalFV, have, fvVersion)
|
||||
}
|
||||
if shouldRemoveNeed(protocol.LocalDeviceID) {
|
||||
meta.removeNeeded(protocol.LocalDeviceID, oldGlobal)
|
||||
@@ -890,7 +902,7 @@ func (t readWriteTransaction) removeFromGlobal(gk, keyBuf, folder, device, file
|
||||
}
|
||||
|
||||
// Nothing left, i.e. nothing to add to the global counter below.
|
||||
if fl.Empty() {
|
||||
if len(fl.Versions) == 0 {
|
||||
if err := t.Delete(gk); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -907,7 +919,7 @@ func (t readWriteTransaction) removeFromGlobal(gk, keyBuf, folder, device, file
|
||||
meta.addFile(protocol.GlobalDeviceID, global)
|
||||
|
||||
l.Debugf(`new global for "%s" after remove: %v`, file, fl)
|
||||
if err := t.Put(gk, mustMarshal(&fl)); err != nil {
|
||||
if err := t.Put(gk, mustMarshal(fl)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -935,7 +947,7 @@ func (t readWriteTransaction) deleteKeyPrefixMatching(prefix []byte, match func(
|
||||
return dbi.Error()
|
||||
}
|
||||
|
||||
func (t *readWriteTransaction) withAllFolderTruncated(folder []byte, fn func(device []byte, f FileInfoTruncated) bool) error {
|
||||
func (t *readWriteTransaction) withAllFolderTruncated(folder []byte, fn func(device []byte, f protocol.FileInfo) bool) error {
|
||||
key, err := t.keyer.GenerateDeviceFileKey(nil, folder, nil, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -957,11 +969,10 @@ func (t *readWriteTransaction) withAllFolderTruncated(folder []byte, fn func(dev
|
||||
continue
|
||||
}
|
||||
|
||||
intf, err := t.unmarshalTrunc(dbi.Value(), true)
|
||||
f, err := t.unmarshalTrunc(dbi.Value(), true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
f := intf.(FileInfoTruncated)
|
||||
|
||||
switch f.Name {
|
||||
case "", ".", "..", "/": // A few obviously invalid filenames
|
||||
@@ -988,12 +999,8 @@ func (t *readWriteTransaction) withAllFolderTruncated(folder []byte, fn func(dev
|
||||
return dbi.Error()
|
||||
}
|
||||
|
||||
type marshaller interface {
|
||||
Marshal() ([]byte, error)
|
||||
}
|
||||
|
||||
func mustMarshal(f marshaller) []byte {
|
||||
bs, err := f.Marshal()
|
||||
func mustMarshal(f proto.Message) []byte {
|
||||
bs, err := proto.Marshal(f)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
+5
-2
@@ -6,7 +6,10 @@
|
||||
|
||||
package db
|
||||
|
||||
import "github.com/syncthing/syncthing/lib/protocol"
|
||||
import (
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
// How many files to send in each Index/IndexUpdate message.
|
||||
const (
|
||||
@@ -44,7 +47,7 @@ func (b *FileInfoBatch) Append(f protocol.FileInfo) {
|
||||
b.infos = make([]protocol.FileInfo, 0, MaxBatchSizeFiles)
|
||||
}
|
||||
b.infos = append(b.infos, f)
|
||||
b.size += f.ProtoSize()
|
||||
b.size += proto.Size(f.ToWire(true))
|
||||
}
|
||||
|
||||
func (b *FileInfoBatch) Full() bool {
|
||||
|
||||
@@ -10,9 +10,8 @@ import (
|
||||
stdsync "sync"
|
||||
"time"
|
||||
|
||||
"github.com/thejerf/suture/v4"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
"github.com/thejerf/suture/v4"
|
||||
)
|
||||
|
||||
// A cachedFinder is a Finder with associated cache timeouts.
|
||||
|
||||
@@ -21,11 +21,12 @@ import (
|
||||
stdsync "sync"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/http2"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/connections/registry"
|
||||
"github.com/syncthing/syncthing/lib/dialer"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
"golang.org/x/net/http2"
|
||||
)
|
||||
|
||||
type globalClient struct {
|
||||
|
||||
+28
-17
@@ -7,6 +7,7 @@
|
||||
package discover
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
@@ -17,12 +18,15 @@ import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/thejerf/suture/v4"
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
"github.com/syncthing/syncthing/internal/gen/discoproto"
|
||||
"github.com/syncthing/syncthing/lib/beacon"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
"github.com/syncthing/syncthing/lib/rand"
|
||||
"github.com/syncthing/syncthing/lib/svcutil"
|
||||
"github.com/thejerf/suture/v4"
|
||||
)
|
||||
|
||||
type localClient struct {
|
||||
@@ -121,12 +125,12 @@ func (c *localClient) announcementPkt(instanceID int64, msg []byte) ([]byte, boo
|
||||
return msg, false
|
||||
}
|
||||
|
||||
pkt := Announce{
|
||||
ID: c.myID,
|
||||
pkt := &discoproto.Announce{
|
||||
Id: c.myID[:],
|
||||
Addresses: addrs,
|
||||
InstanceID: instanceID,
|
||||
InstanceId: instanceID,
|
||||
}
|
||||
bs, _ := pkt.Marshal()
|
||||
bs, _ := proto.Marshal(pkt)
|
||||
|
||||
if pktLen := 4 + len(bs); cap(msg) < pktLen {
|
||||
msg = make([]byte, 0, pktLen)
|
||||
@@ -193,18 +197,19 @@ func (c *localClient) recvAnnouncements(ctx context.Context) error {
|
||||
continue
|
||||
}
|
||||
|
||||
var pkt Announce
|
||||
err := pkt.Unmarshal(buf[4:])
|
||||
var pkt discoproto.Announce
|
||||
err := proto.Unmarshal(buf[:4], &pkt)
|
||||
if err != nil && err != io.EOF {
|
||||
l.Debugf("discover: Failed to unmarshal local announcement from %s:\n%s", addr, hex.Dump(buf))
|
||||
continue
|
||||
}
|
||||
|
||||
l.Debugf("discover: Received local announcement from %s for %s", addr, pkt.ID)
|
||||
id, _ := protocol.DeviceIDFromBytes(pkt.Id)
|
||||
l.Debugf("discover: Received local announcement from %s for %s", addr, id)
|
||||
|
||||
var newDevice bool
|
||||
if pkt.ID != c.myID {
|
||||
newDevice = c.registerDevice(addr, pkt)
|
||||
if !bytes.Equal(pkt.Id, c.myID[:]) {
|
||||
newDevice = c.registerDevice(addr, &pkt)
|
||||
}
|
||||
|
||||
if newDevice {
|
||||
@@ -218,18 +223,24 @@ func (c *localClient) recvAnnouncements(ctx context.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *localClient) registerDevice(src net.Addr, device Announce) bool {
|
||||
func (c *localClient) registerDevice(src net.Addr, device *discoproto.Announce) bool {
|
||||
// Remember whether we already had a valid cache entry for this device.
|
||||
// If the instance ID has changed the remote device has restarted since
|
||||
// we last heard from it, so we should treat it as a new device.
|
||||
|
||||
ce, existsAlready := c.Get(device.ID)
|
||||
isNewDevice := !existsAlready || time.Since(ce.when) > CacheLifeTime || ce.instanceID != device.InstanceID
|
||||
id, err := protocol.DeviceIDFromBytes(device.Id)
|
||||
if err != nil {
|
||||
l.Debugf("discover: Failed to parse device ID %x: %v", device.Id, err)
|
||||
return false
|
||||
}
|
||||
|
||||
ce, existsAlready := c.Get(id)
|
||||
isNewDevice := !existsAlready || time.Since(ce.when) > CacheLifeTime || ce.instanceID != device.InstanceId
|
||||
|
||||
// Any empty or unspecified addresses should be set to the source address
|
||||
// of the announcement. We also skip any addresses we can't parse.
|
||||
|
||||
l.Debugln("discover: Registering addresses for", device.ID)
|
||||
l.Debugln("discover: Registering addresses for", id)
|
||||
var validAddresses []string
|
||||
for _, addr := range device.Addresses {
|
||||
u, err := url.Parse(addr)
|
||||
@@ -272,16 +283,16 @@ func (c *localClient) registerDevice(src net.Addr, device Announce) bool {
|
||||
}
|
||||
}
|
||||
|
||||
c.Set(device.ID, CacheEntry{
|
||||
c.Set(id, CacheEntry{
|
||||
Addresses: validAddresses,
|
||||
when: time.Now(),
|
||||
found: true,
|
||||
instanceID: device.InstanceID,
|
||||
instanceID: device.InstanceId,
|
||||
})
|
||||
|
||||
if isNewDevice {
|
||||
c.evLogger.Log(events.DeviceDiscovered, map[string]interface{}{
|
||||
"device": device.ID.String(),
|
||||
"device": id.String(),
|
||||
"addrs": validAddresses,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,399 +0,0 @@
|
||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: lib/discover/local.proto
|
||||
|
||||
package discover
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
_ "github.com/gogo/protobuf/gogoproto"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
github_com_syncthing_syncthing_lib_protocol "github.com/syncthing/syncthing/lib/protocol"
|
||||
_ "github.com/syncthing/syncthing/proto/ext"
|
||||
io "io"
|
||||
math "math"
|
||||
math_bits "math/bits"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
type Announce struct {
|
||||
ID github_com_syncthing_syncthing_lib_protocol.DeviceID `protobuf:"bytes,1,opt,name=id,proto3,customtype=github.com/syncthing/syncthing/lib/protocol.DeviceID" json:"id" xml:"id"`
|
||||
Addresses []string `protobuf:"bytes,2,rep,name=addresses,proto3" json:"addresses" xml:"address"`
|
||||
InstanceID int64 `protobuf:"varint,3,opt,name=instance_id,json=instanceId,proto3" json:"instanceId" xml:"instanceId"`
|
||||
}
|
||||
|
||||
func (m *Announce) Reset() { *m = Announce{} }
|
||||
func (m *Announce) String() string { return proto.CompactTextString(m) }
|
||||
func (*Announce) ProtoMessage() {}
|
||||
func (*Announce) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_18afca46562fdaf4, []int{0}
|
||||
}
|
||||
func (m *Announce) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *Announce) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_Announce.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *Announce) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Announce.Merge(m, src)
|
||||
}
|
||||
func (m *Announce) XXX_Size() int {
|
||||
return m.ProtoSize()
|
||||
}
|
||||
func (m *Announce) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Announce.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Announce proto.InternalMessageInfo
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Announce)(nil), "discover.Announce")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("lib/discover/local.proto", fileDescriptor_18afca46562fdaf4) }
|
||||
|
||||
var fileDescriptor_18afca46562fdaf4 = []byte{
|
||||
// 334 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x91, 0x31, 0x6b, 0xe3, 0x30,
|
||||
0x18, 0x86, 0x2d, 0x05, 0x8e, 0x44, 0x77, 0x07, 0x87, 0x27, 0x93, 0x41, 0x0a, 0xbe, 0x0c, 0x81,
|
||||
0x42, 0x3c, 0xb4, 0x53, 0x29, 0x85, 0x1a, 0x2f, 0x1e, 0xba, 0x64, 0xec, 0xd0, 0x10, 0x4b, 0xaa,
|
||||
0x23, 0x70, 0xa4, 0x60, 0x39, 0x21, 0xfd, 0x07, 0x1d, 0x4b, 0xb6, 0x6e, 0xfd, 0x39, 0x19, 0x3d,
|
||||
0x96, 0x0e, 0x82, 0xd8, 0x5b, 0xc6, 0xfc, 0x82, 0x12, 0x25, 0x69, 0x32, 0x76, 0x7b, 0xf5, 0xe8,
|
||||
0x95, 0x78, 0xf8, 0x3e, 0xe4, 0x65, 0x22, 0x09, 0x98, 0xd0, 0x54, 0xcd, 0x79, 0x1e, 0x64, 0x8a,
|
||||
0x8e, 0xb2, 0xfe, 0x34, 0x57, 0x85, 0x72, 0x9b, 0x47, 0xda, 0xfe, 0x9f, 0xf3, 0xa9, 0xd2, 0x81,
|
||||
0xc5, 0xc9, 0xec, 0x29, 0x48, 0x55, 0xaa, 0xec, 0xc1, 0xa6, 0x7d, 0xbd, 0xdd, 0xe2, 0x8b, 0x62,
|
||||
0x1f, 0xfd, 0x37, 0x88, 0x9a, 0x77, 0x52, 0xaa, 0x99, 0xa4, 0xdc, 0x95, 0x08, 0x0a, 0xe6, 0x81,
|
||||
0x0e, 0xe8, 0xfd, 0x09, 0x1f, 0x57, 0x86, 0x38, 0x9f, 0x86, 0x5c, 0xa5, 0xa2, 0x18, 0xcf, 0x92,
|
||||
0x3e, 0x55, 0x93, 0x40, 0x3f, 0x4b, 0x5a, 0x8c, 0x85, 0x4c, 0xcf, 0xd2, 0xce, 0xc9, 0x7e, 0x45,
|
||||
0x55, 0xd6, 0x8f, 0xf8, 0x5c, 0x50, 0x1e, 0x47, 0x95, 0x21, 0x30, 0x8e, 0x36, 0x86, 0x40, 0xc1,
|
||||
0xb6, 0x86, 0x34, 0x17, 0x93, 0xec, 0xda, 0x17, 0xcc, 0x7f, 0x29, 0xbb, 0x60, 0x59, 0x76, 0x61,
|
||||
0x1c, 0x0d, 0xa0, 0x60, 0xee, 0x0d, 0x6a, 0x8d, 0x18, 0xcb, 0xb9, 0xd6, 0x5c, 0x7b, 0xb0, 0xd3,
|
||||
0xe8, 0xb5, 0x42, 0xbc, 0x31, 0xe4, 0x04, 0xb7, 0x86, 0xfc, 0xb5, 0x6f, 0x0f, 0xc4, 0x1f, 0x9c,
|
||||
0xee, 0xdc, 0x21, 0xfa, 0x2d, 0xa4, 0x2e, 0x46, 0x92, 0xf2, 0xa1, 0x60, 0x5e, 0xa3, 0x03, 0x7a,
|
||||
0x8d, 0xf0, 0xb6, 0x32, 0x04, 0xc5, 0x07, 0x6c, 0x15, 0xd0, 0xb1, 0x14, 0xef, 0x54, 0xfe, 0xed,
|
||||
0x55, 0xbe, 0x91, 0xbf, 0x2c, 0xbb, 0x67, 0xfd, 0xc1, 0x59, 0x3b, 0xbc, 0x5f, 0xad, 0xb1, 0x53,
|
||||
0xae, 0xb1, 0xb3, 0xaa, 0x30, 0x28, 0x2b, 0x0c, 0x5e, 0x6b, 0xec, 0xbc, 0xd7, 0x18, 0x94, 0x35,
|
||||
0x76, 0x3e, 0x6a, 0xec, 0x3c, 0x5c, 0xfc, 0x60, 0x38, 0xc7, 0xd5, 0x24, 0xbf, 0xec, 0x98, 0x2e,
|
||||
0xbf, 0x02, 0x00, 0x00, 0xff, 0xff, 0xdc, 0xe8, 0x9a, 0xd0, 0xc7, 0x01, 0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *Announce) Marshal() (dAtA []byte, err error) {
|
||||
size := m.ProtoSize()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *Announce) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.ProtoSize()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *Announce) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.InstanceID != 0 {
|
||||
i = encodeVarintLocal(dAtA, i, uint64(m.InstanceID))
|
||||
i--
|
||||
dAtA[i] = 0x18
|
||||
}
|
||||
if len(m.Addresses) > 0 {
|
||||
for iNdEx := len(m.Addresses) - 1; iNdEx >= 0; iNdEx-- {
|
||||
i -= len(m.Addresses[iNdEx])
|
||||
copy(dAtA[i:], m.Addresses[iNdEx])
|
||||
i = encodeVarintLocal(dAtA, i, uint64(len(m.Addresses[iNdEx])))
|
||||
i--
|
||||
dAtA[i] = 0x12
|
||||
}
|
||||
}
|
||||
{
|
||||
size := m.ID.ProtoSize()
|
||||
i -= size
|
||||
if _, err := m.ID.MarshalTo(dAtA[i:]); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i = encodeVarintLocal(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func encodeVarintLocal(dAtA []byte, offset int, v uint64) int {
|
||||
offset -= sovLocal(v)
|
||||
base := offset
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return base
|
||||
}
|
||||
func (m *Announce) ProtoSize() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
l = m.ID.ProtoSize()
|
||||
n += 1 + l + sovLocal(uint64(l))
|
||||
if len(m.Addresses) > 0 {
|
||||
for _, s := range m.Addresses {
|
||||
l = len(s)
|
||||
n += 1 + l + sovLocal(uint64(l))
|
||||
}
|
||||
}
|
||||
if m.InstanceID != 0 {
|
||||
n += 1 + sovLocal(uint64(m.InstanceID))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovLocal(x uint64) (n int) {
|
||||
return (math_bits.Len64(x|1) + 6) / 7
|
||||
}
|
||||
func sozLocal(x uint64) (n int) {
|
||||
return sovLocal(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (m *Announce) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowLocal
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: Announce: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: Announce: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType)
|
||||
}
|
||||
var byteLen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowLocal
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
byteLen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if byteLen < 0 {
|
||||
return ErrInvalidLengthLocal
|
||||
}
|
||||
postIndex := iNdEx + byteLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthLocal
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := m.ID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Addresses", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowLocal
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthLocal
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthLocal
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Addresses = append(m.Addresses, string(dAtA[iNdEx:postIndex]))
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field InstanceID", wireType)
|
||||
}
|
||||
m.InstanceID = 0
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowLocal
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.InstanceID |= int64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipLocal(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthLocal
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipLocal(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
depth := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowLocal
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowLocal
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if dAtA[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowLocal
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthLocal
|
||||
}
|
||||
iNdEx += length
|
||||
case 3:
|
||||
depth++
|
||||
case 4:
|
||||
if depth == 0 {
|
||||
return 0, ErrUnexpectedEndOfGroupLocal
|
||||
}
|
||||
depth--
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
if iNdEx < 0 {
|
||||
return 0, ErrInvalidLengthLocal
|
||||
}
|
||||
if depth == 0 {
|
||||
return iNdEx, nil
|
||||
}
|
||||
}
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthLocal = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowLocal = fmt.Errorf("proto: integer overflow")
|
||||
ErrUnexpectedEndOfGroupLocal = fmt.Errorf("proto: unexpected end of group")
|
||||
)
|
||||
+19
-12
@@ -13,6 +13,7 @@ import (
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/syncthing/syncthing/internal/gen/discoproto"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
)
|
||||
@@ -50,40 +51,40 @@ func TestLocalInstanceIDShouldTriggerNew(t *testing.T) {
|
||||
lc := c.(*localClient)
|
||||
src := &net.UDPAddr{IP: []byte{10, 20, 30, 40}, Port: 50}
|
||||
|
||||
new := lc.registerDevice(src, Announce{
|
||||
ID: protocol.DeviceID{10, 20, 30, 40, 50, 60, 70, 80, 90},
|
||||
new := lc.registerDevice(src, &discoproto.Announce{
|
||||
Id: padDeviceID(10),
|
||||
Addresses: []string{"tcp://0.0.0.0:22000"},
|
||||
InstanceID: 1234567890,
|
||||
InstanceId: 1234567890,
|
||||
})
|
||||
|
||||
if !new {
|
||||
t.Fatal("first register should be new")
|
||||
}
|
||||
|
||||
new = lc.registerDevice(src, Announce{
|
||||
ID: protocol.DeviceID{10, 20, 30, 40, 50, 60, 70, 80, 90},
|
||||
new = lc.registerDevice(src, &discoproto.Announce{
|
||||
Id: padDeviceID(10),
|
||||
Addresses: []string{"tcp://0.0.0.0:22000"},
|
||||
InstanceID: 1234567890,
|
||||
InstanceId: 1234567890,
|
||||
})
|
||||
|
||||
if new {
|
||||
t.Fatal("second register should not be new")
|
||||
}
|
||||
|
||||
new = lc.registerDevice(src, Announce{
|
||||
ID: protocol.DeviceID{42, 10, 20, 30, 40, 50, 60, 70, 80, 90},
|
||||
new = lc.registerDevice(src, &discoproto.Announce{
|
||||
Id: padDeviceID(42),
|
||||
Addresses: []string{"tcp://0.0.0.0:22000"},
|
||||
InstanceID: 1234567890,
|
||||
InstanceId: 1234567890,
|
||||
})
|
||||
|
||||
if !new {
|
||||
t.Fatal("new device ID should be new")
|
||||
}
|
||||
|
||||
new = lc.registerDevice(src, Announce{
|
||||
ID: protocol.DeviceID{10, 20, 30, 40, 50, 60, 70, 80, 90},
|
||||
new = lc.registerDevice(src, &discoproto.Announce{
|
||||
Id: padDeviceID(10),
|
||||
Addresses: []string{"tcp://0.0.0.0:22000"},
|
||||
InstanceID: 91234567890,
|
||||
InstanceId: 91234567890,
|
||||
})
|
||||
|
||||
if !new {
|
||||
@@ -91,6 +92,12 @@ func TestLocalInstanceIDShouldTriggerNew(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func padDeviceID(bs ...byte) []byte {
|
||||
var padded [32]byte
|
||||
copy(padded[:], bs)
|
||||
return padded[:]
|
||||
}
|
||||
|
||||
func TestFilterUndialable(t *testing.T) {
|
||||
addrs := []string{
|
||||
"quic://[2001:db8::1]:22000", // OK
|
||||
|
||||
@@ -9,9 +9,7 @@
|
||||
|
||||
package fs
|
||||
|
||||
import (
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
)
|
||||
import "github.com/syncthing/syncthing/lib/protocol"
|
||||
|
||||
func (f *BasicFilesystem) PlatformData(name string, scanOwnership, scanXattrs bool, xattrFilter XattrFilter) (protocol.PlatformData, error) {
|
||||
return unixPlatformData(f, name, f.userCache, f.groupCache, scanOwnership, scanXattrs, xattrFilter)
|
||||
|
||||
@@ -9,6 +9,6 @@
|
||||
|
||||
package fs
|
||||
|
||||
func reachedMaxUserWatches(err error) bool {
|
||||
func reachedMaxUserWatches(_ error) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -9,9 +9,7 @@
|
||||
|
||||
package fs
|
||||
|
||||
import (
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
)
|
||||
import "github.com/syncthing/syncthing/lib/protocol"
|
||||
|
||||
func (f *BasicFilesystem) GetXattr(path string, xattrFilter XattrFilter) ([]protocol.Xattr, error) {
|
||||
return nil, ErrXattrsNotSupported
|
||||
|
||||
+11
-28
@@ -6,6 +6,17 @@
|
||||
|
||||
package fs
|
||||
|
||||
type CopyRangeMethod int32
|
||||
|
||||
const (
|
||||
CopyRangeMethodStandard CopyRangeMethod = 0
|
||||
CopyRangeMethodIoctl CopyRangeMethod = 1
|
||||
CopyRangeMethodCopyFileRange CopyRangeMethod = 2
|
||||
CopyRangeMethodSendFile CopyRangeMethod = 3
|
||||
CopyRangeMethodDuplicateExtents CopyRangeMethod = 4
|
||||
CopyRangeMethodAllWithFallback CopyRangeMethod = 5
|
||||
)
|
||||
|
||||
func (o CopyRangeMethod) String() string {
|
||||
switch o {
|
||||
case CopyRangeMethodStandard:
|
||||
@@ -24,31 +35,3 @@ func (o CopyRangeMethod) String() string {
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
func (o CopyRangeMethod) MarshalText() ([]byte, error) {
|
||||
return []byte(o.String()), nil
|
||||
}
|
||||
|
||||
func (o *CopyRangeMethod) UnmarshalText(bs []byte) error {
|
||||
switch string(bs) {
|
||||
case "standard":
|
||||
*o = CopyRangeMethodStandard
|
||||
case "ioctl":
|
||||
*o = CopyRangeMethodIoctl
|
||||
case "copy_file_range":
|
||||
*o = CopyRangeMethodCopyFileRange
|
||||
case "sendfile":
|
||||
*o = CopyRangeMethodSendFile
|
||||
case "duplicate_extents":
|
||||
*o = CopyRangeMethodDuplicateExtents
|
||||
case "all":
|
||||
*o = CopyRangeMethodAllWithFallback
|
||||
default:
|
||||
*o = CopyRangeMethodStandard
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *CopyRangeMethod) ParseDefault(str string) error {
|
||||
return o.UnmarshalText([]byte(str))
|
||||
}
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: lib/fs/copyrangemethod.proto
|
||||
|
||||
package fs
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
_ "github.com/gogo/protobuf/gogoproto"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
type CopyRangeMethod int32
|
||||
|
||||
const (
|
||||
CopyRangeMethodStandard CopyRangeMethod = 0
|
||||
CopyRangeMethodIoctl CopyRangeMethod = 1
|
||||
CopyRangeMethodCopyFileRange CopyRangeMethod = 2
|
||||
CopyRangeMethodSendFile CopyRangeMethod = 3
|
||||
CopyRangeMethodDuplicateExtents CopyRangeMethod = 4
|
||||
CopyRangeMethodAllWithFallback CopyRangeMethod = 5
|
||||
)
|
||||
|
||||
var CopyRangeMethod_name = map[int32]string{
|
||||
0: "COPY_RANGE_METHOD_STANDARD",
|
||||
1: "COPY_RANGE_METHOD_IOCTL",
|
||||
2: "COPY_RANGE_METHOD_COPY_FILE_RANGE",
|
||||
3: "COPY_RANGE_METHOD_SEND_FILE",
|
||||
4: "COPY_RANGE_METHOD_DUPLICATE_EXTENTS",
|
||||
5: "COPY_RANGE_METHOD_ALL_WITH_FALLBACK",
|
||||
}
|
||||
|
||||
var CopyRangeMethod_value = map[string]int32{
|
||||
"COPY_RANGE_METHOD_STANDARD": 0,
|
||||
"COPY_RANGE_METHOD_IOCTL": 1,
|
||||
"COPY_RANGE_METHOD_COPY_FILE_RANGE": 2,
|
||||
"COPY_RANGE_METHOD_SEND_FILE": 3,
|
||||
"COPY_RANGE_METHOD_DUPLICATE_EXTENTS": 4,
|
||||
"COPY_RANGE_METHOD_ALL_WITH_FALLBACK": 5,
|
||||
}
|
||||
|
||||
func (CopyRangeMethod) EnumDescriptor() ([]byte, []int) {
|
||||
return fileDescriptor_78e1061c3022e87e, []int{0}
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterEnum("fs.CopyRangeMethod", CopyRangeMethod_name, CopyRangeMethod_value)
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("lib/fs/copyrangemethod.proto", fileDescriptor_78e1061c3022e87e) }
|
||||
|
||||
var fileDescriptor_78e1061c3022e87e = []byte{
|
||||
// 391 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x92, 0xbd, 0x8e, 0xd3, 0x40,
|
||||
0x14, 0x85, 0xed, 0xdd, 0x85, 0xc2, 0x0d, 0x96, 0x85, 0xb4, 0x68, 0x76, 0x35, 0x18, 0x22, 0x1a,
|
||||
0x8a, 0x75, 0x81, 0xa8, 0xa0, 0x99, 0xb5, 0xc7, 0x59, 0x6b, 0x27, 0x4e, 0x94, 0x18, 0x05, 0x68,
|
||||
0x2c, 0xff, 0xc5, 0xb6, 0x98, 0x78, 0x2c, 0x7b, 0x22, 0x91, 0x57, 0x70, 0xc5, 0x0b, 0x58, 0xa2,
|
||||
0xa0, 0xa0, 0xe1, 0x3d, 0x52, 0xa6, 0xa4, 0x4d, 0xfc, 0x22, 0x28, 0x93, 0x06, 0x39, 0xe9, 0xee,
|
||||
0x3d, 0x9a, 0xef, 0xd3, 0x91, 0xe6, 0x2a, 0xb7, 0x34, 0x0f, 0x8d, 0x45, 0x6d, 0x44, 0xac, 0x5c,
|
||||
0x57, 0x41, 0x91, 0x26, 0xcb, 0x84, 0x67, 0x2c, 0xbe, 0x2b, 0x2b, 0xc6, 0x99, 0x76, 0xb1, 0xa8,
|
||||
0xc1, 0xa0, 0x4a, 0x4a, 0x56, 0x1b, 0x22, 0x08, 0x57, 0x0b, 0x23, 0x65, 0x29, 0x13, 0x8b, 0x98,
|
||||
0x8e, 0x0f, 0xdf, 0xfe, 0xb9, 0x54, 0x9e, 0x99, 0xac, 0x5c, 0x4f, 0x0f, 0x8a, 0x91, 0x50, 0x68,
|
||||
0x1f, 0x14, 0x60, 0x8e, 0x27, 0x5f, 0xfc, 0x29, 0x72, 0x87, 0xd8, 0x1f, 0x61, 0xef, 0x61, 0x6c,
|
||||
0xf9, 0x33, 0x0f, 0xb9, 0x16, 0x9a, 0x5a, 0xaa, 0x04, 0x6e, 0x9a, 0x56, 0xbf, 0xee, 0x41, 0x33,
|
||||
0x1e, 0x14, 0x71, 0x50, 0xc5, 0xda, 0x7b, 0xe5, 0xfa, 0x14, 0x76, 0xc6, 0xa6, 0x47, 0x54, 0x19,
|
||||
0xbc, 0x68, 0x5a, 0xfd, 0x79, 0x8f, 0x74, 0x58, 0xc4, 0xa9, 0x36, 0x54, 0x5e, 0x9d, 0x62, 0x22,
|
||||
0xb1, 0x1d, 0x82, 0x8f, 0xb1, 0x7a, 0x01, 0xf4, 0xa6, 0xd5, 0x6f, 0x7b, 0x82, 0xc3, 0x6a, 0xe7,
|
||||
0x34, 0x11, 0x91, 0xf6, 0x51, 0xb9, 0x39, 0x53, 0x1e, 0xbb, 0x96, 0x10, 0xa9, 0x97, 0xe7, 0xdb,
|
||||
0x27, 0x45, 0x7c, 0x50, 0x68, 0x44, 0x19, 0x9c, 0xd2, 0xd6, 0xa7, 0x09, 0x71, 0x4c, 0xe4, 0x61,
|
||||
0x1f, 0x7f, 0xf6, 0xb0, 0xeb, 0xcd, 0xd4, 0x2b, 0x30, 0x68, 0x5a, 0xfd, 0x65, 0xcf, 0x62, 0xad,
|
||||
0x4a, 0x9a, 0x47, 0x01, 0x4f, 0xf0, 0x77, 0x9e, 0x14, 0xbc, 0xd6, 0x1e, 0xcf, 0xd9, 0x10, 0x21,
|
||||
0xfe, 0xdc, 0xf1, 0x1e, 0x7c, 0x1b, 0x11, 0x72, 0x8f, 0xcc, 0x47, 0xf5, 0x09, 0x78, 0xdd, 0xb4,
|
||||
0x3a, 0xec, 0xd9, 0x10, 0xa5, 0xf3, 0x9c, 0x67, 0x76, 0x40, 0x69, 0x18, 0x44, 0xdf, 0xc0, 0xd5,
|
||||
0xef, 0x5f, 0x50, 0xba, 0x1f, 0x6e, 0x76, 0x50, 0xda, 0xee, 0xa0, 0xb4, 0xd9, 0x43, 0x79, 0xbb,
|
||||
0x87, 0xf2, 0x8f, 0x0e, 0x4a, 0x3f, 0x3b, 0x28, 0x6f, 0x3b, 0x28, 0xfd, 0xed, 0xa0, 0xf4, 0xf5,
|
||||
0x4d, 0x9a, 0xf3, 0x6c, 0x15, 0xde, 0x45, 0x6c, 0x69, 0xd4, 0xeb, 0x22, 0xe2, 0x59, 0x5e, 0xa4,
|
||||
0xff, 0x4d, 0xc7, 0xbb, 0x09, 0x9f, 0x8a, 0xff, 0x7f, 0xf7, 0x2f, 0x00, 0x00, 0xff, 0xff, 0xb6,
|
||||
0x5d, 0x2e, 0x16, 0x48, 0x02, 0x00, 0x00,
|
||||
}
|
||||
+7
-16
@@ -6,6 +6,13 @@
|
||||
|
||||
package fs
|
||||
|
||||
type FilesystemType int32
|
||||
|
||||
const (
|
||||
FilesystemTypeBasic FilesystemType = 0
|
||||
FilesystemTypeFake FilesystemType = 1
|
||||
)
|
||||
|
||||
func (t FilesystemType) String() string {
|
||||
switch t {
|
||||
case FilesystemTypeBasic:
|
||||
@@ -16,19 +23,3 @@ func (t FilesystemType) String() string {
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
func (t FilesystemType) MarshalText() ([]byte, error) {
|
||||
return []byte(t.String()), nil
|
||||
}
|
||||
|
||||
func (t *FilesystemType) UnmarshalText(bs []byte) error {
|
||||
switch string(bs) {
|
||||
case "basic":
|
||||
*t = FilesystemTypeBasic
|
||||
case "fake":
|
||||
*t = FilesystemTypeFake
|
||||
default:
|
||||
*t = FilesystemTypeBasic
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: lib/fs/types.proto
|
||||
|
||||
package fs
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
_ "github.com/gogo/protobuf/gogoproto"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
type FilesystemType int32
|
||||
|
||||
const (
|
||||
FilesystemTypeBasic FilesystemType = 0
|
||||
FilesystemTypeFake FilesystemType = 1
|
||||
)
|
||||
|
||||
var FilesystemType_name = map[int32]string{
|
||||
0: "FILESYSTEM_TYPE_BASIC",
|
||||
1: "FILESYSTEM_TYPE_FAKE",
|
||||
}
|
||||
|
||||
var FilesystemType_value = map[string]int32{
|
||||
"FILESYSTEM_TYPE_BASIC": 0,
|
||||
"FILESYSTEM_TYPE_FAKE": 1,
|
||||
}
|
||||
|
||||
func (FilesystemType) EnumDescriptor() ([]byte, []int) {
|
||||
return fileDescriptor_b556f45c4309ad5d, []int{0}
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterEnum("fs.FilesystemType", FilesystemType_name, FilesystemType_value)
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("lib/fs/types.proto", fileDescriptor_b556f45c4309ad5d) }
|
||||
|
||||
var fileDescriptor_b556f45c4309ad5d = []byte{
|
||||
// 228 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xca, 0xc9, 0x4c, 0xd2,
|
||||
0x4f, 0x2b, 0xd6, 0x2f, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62,
|
||||
0x4a, 0x2b, 0x96, 0x52, 0x2e, 0x4a, 0x2d, 0xc8, 0x2f, 0xd6, 0x07, 0x0b, 0x24, 0x95, 0xa6, 0xe9,
|
||||
0xa7, 0xe7, 0xa7, 0xe7, 0x83, 0x39, 0x60, 0x16, 0x44, 0xa1, 0x56, 0x0d, 0x17, 0x9f, 0x5b, 0x66,
|
||||
0x4e, 0x6a, 0x71, 0x65, 0x71, 0x49, 0x6a, 0x6e, 0x48, 0x65, 0x41, 0xaa, 0x90, 0x11, 0x97, 0xa8,
|
||||
0x9b, 0xa7, 0x8f, 0x6b, 0x70, 0x64, 0x70, 0x88, 0xab, 0x6f, 0x7c, 0x48, 0x64, 0x80, 0x6b, 0xbc,
|
||||
0x93, 0x63, 0xb0, 0xa7, 0xb3, 0x00, 0x83, 0x94, 0x78, 0xd7, 0x5c, 0x05, 0x61, 0x54, 0xe5, 0x4e,
|
||||
0x89, 0xc5, 0x99, 0xc9, 0x42, 0x06, 0x5c, 0x22, 0xe8, 0x7a, 0xdc, 0x1c, 0xbd, 0x5d, 0x05, 0x18,
|
||||
0xa5, 0xc4, 0xba, 0xe6, 0x2a, 0x08, 0xa1, 0x6a, 0x71, 0x4b, 0xcc, 0x4e, 0x95, 0x62, 0x59, 0xb1,
|
||||
0x44, 0x8e, 0xc1, 0xc9, 0xfd, 0xc4, 0x43, 0x39, 0x86, 0x0b, 0x0f, 0xe5, 0x18, 0x4e, 0x3c, 0x92,
|
||||
0x63, 0xbc, 0xf0, 0x48, 0x8e, 0x71, 0xc2, 0x63, 0x39, 0x86, 0x05, 0x8f, 0xe5, 0x18, 0x2f, 0x3c,
|
||||
0x96, 0x63, 0xb8, 0xf1, 0x58, 0x8e, 0x21, 0x4a, 0x35, 0x3d, 0xb3, 0x24, 0xa3, 0x34, 0x49, 0x2f,
|
||||
0x39, 0x3f, 0x57, 0xbf, 0xb8, 0x32, 0x2f, 0xb9, 0x24, 0x23, 0x33, 0x2f, 0x1d, 0x89, 0x05, 0xf1,
|
||||
0x7b, 0x12, 0x1b, 0xd8, 0x37, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x2c, 0x30, 0x9a, 0x86,
|
||||
0x0c, 0x01, 0x00, 0x00,
|
||||
}
|
||||
@@ -90,7 +90,7 @@ func (f *fakeConnection) addFileLocked(name string, flags uint32, ftype protocol
|
||||
file.Permissions = flags
|
||||
if ftype == protocol.FileInfoTypeFile {
|
||||
file.Size = int64(len(data))
|
||||
file.RawBlockSize = blockSize
|
||||
file.RawBlockSize = int32(blockSize)
|
||||
file.Blocks = blocks
|
||||
}
|
||||
default: // Symlink
|
||||
|
||||
+35
-35
@@ -372,7 +372,7 @@ func (f *folder) pull() (success bool, err error) {
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
snap.WithNeed(protocol.LocalDeviceID, func(intf protocol.FileIntf) bool {
|
||||
snap.WithNeed(protocol.LocalDeviceID, func(intf protocol.FileInfo) bool {
|
||||
abort = false
|
||||
return false
|
||||
})
|
||||
@@ -702,7 +702,7 @@ func (f *folder) scanSubdirsChangedAndNew(subDirs []string, batch *scanBatch) (i
|
||||
}
|
||||
|
||||
func (f *folder) scanSubdirsDeletedAndIgnored(subDirs []string, batch *scanBatch) (int, error) {
|
||||
var toIgnore []db.FileInfoTruncated
|
||||
var toIgnore []protocol.FileInfo
|
||||
ignoredParent := ""
|
||||
changes := 0
|
||||
snap, err := f.dbSnapshot()
|
||||
@@ -714,24 +714,23 @@ func (f *folder) scanSubdirsDeletedAndIgnored(subDirs []string, batch *scanBatch
|
||||
for _, sub := range subDirs {
|
||||
var iterError error
|
||||
|
||||
snap.WithPrefixedHaveTruncated(protocol.LocalDeviceID, sub, func(fi protocol.FileIntf) bool {
|
||||
snap.WithPrefixedHaveTruncated(protocol.LocalDeviceID, sub, func(fi protocol.FileInfo) bool {
|
||||
select {
|
||||
case <-f.ctx.Done():
|
||||
return false
|
||||
default:
|
||||
}
|
||||
|
||||
file := fi.(db.FileInfoTruncated)
|
||||
|
||||
if err := batch.FlushIfFull(); err != nil {
|
||||
iterError = err
|
||||
return false
|
||||
}
|
||||
|
||||
if ignoredParent != "" && !fs.IsParent(file.Name, ignoredParent) {
|
||||
if ignoredParent != "" && !fs.IsParent(fi.Name, ignoredParent) {
|
||||
for _, file := range toIgnore {
|
||||
l.Debugln("marking file as ignored", file)
|
||||
nf := file.ConvertToIgnoredFileInfo()
|
||||
nf := file
|
||||
nf.SetIgnored()
|
||||
if batch.Update(nf, snap) {
|
||||
changes++
|
||||
}
|
||||
@@ -744,38 +743,39 @@ func (f *folder) scanSubdirsDeletedAndIgnored(subDirs []string, batch *scanBatch
|
||||
ignoredParent = ""
|
||||
}
|
||||
|
||||
switch ignored := f.ignores.Match(file.Name).IsIgnored(); {
|
||||
case file.IsIgnored() && ignored:
|
||||
switch ignored := f.ignores.Match(fi.Name).IsIgnored(); {
|
||||
case fi.IsIgnored() && ignored:
|
||||
return true
|
||||
case !file.IsIgnored() && ignored:
|
||||
case !fi.IsIgnored() && ignored:
|
||||
// File was not ignored at last pass but has been ignored.
|
||||
if file.IsDirectory() {
|
||||
if fi.IsDirectory() {
|
||||
// Delay ignoring as a child might be unignored.
|
||||
toIgnore = append(toIgnore, file)
|
||||
toIgnore = append(toIgnore, fi)
|
||||
if ignoredParent == "" {
|
||||
// If the parent wasn't ignored already, set
|
||||
// this path as the "highest" ignored parent
|
||||
ignoredParent = file.Name
|
||||
ignoredParent = fi.Name
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
l.Debugln("marking file as ignored", file)
|
||||
nf := file.ConvertToIgnoredFileInfo()
|
||||
l.Debugln("marking file as ignored", fi)
|
||||
nf := fi
|
||||
nf.SetIgnored()
|
||||
if batch.Update(nf, snap) {
|
||||
changes++
|
||||
}
|
||||
|
||||
case file.IsIgnored() && !ignored:
|
||||
case fi.IsIgnored() && !ignored:
|
||||
// Successfully scanned items are already un-ignored during
|
||||
// the scan, so check whether it is deleted.
|
||||
fallthrough
|
||||
case !file.IsIgnored() && !file.IsDeleted() && !file.IsUnsupported():
|
||||
case !fi.IsIgnored() && !fi.IsDeleted() && !fi.IsUnsupported():
|
||||
// The file is not ignored, deleted or unsupported. Lets check if
|
||||
// it's still here. Simply stat:ing it won't do as there are
|
||||
// tons of corner cases (e.g. parent dir->symlink, missing
|
||||
// permissions)
|
||||
if !osutil.IsDeleted(f.mtimefs, file.Name) {
|
||||
if !osutil.IsDeleted(f.mtimefs, fi.Name) {
|
||||
if ignoredParent != "" {
|
||||
// Don't ignore parents of this not ignored item
|
||||
toIgnore = toIgnore[:0]
|
||||
@@ -783,9 +783,10 @@ func (f *folder) scanSubdirsDeletedAndIgnored(subDirs []string, batch *scanBatch
|
||||
}
|
||||
return true
|
||||
}
|
||||
nf := file.ConvertToDeletedFileInfo(f.shortID)
|
||||
nf := fi
|
||||
nf.SetDeleted(f.shortID)
|
||||
nf.LocalFlags = f.localFlags
|
||||
if file.ShouldConflict() {
|
||||
if fi.ShouldConflict() {
|
||||
// We do not want to override the global version with
|
||||
// the deleted file. Setting to an empty version makes
|
||||
// sure the file gets in sync on the following pull.
|
||||
@@ -795,30 +796,30 @@ func (f *folder) scanSubdirsDeletedAndIgnored(subDirs []string, batch *scanBatch
|
||||
if batch.Update(nf, snap) {
|
||||
changes++
|
||||
}
|
||||
case file.IsDeleted() && file.IsReceiveOnlyChanged():
|
||||
case fi.IsDeleted() && fi.IsReceiveOnlyChanged():
|
||||
switch f.Type {
|
||||
case config.FolderTypeReceiveOnly, config.FolderTypeReceiveEncrypted:
|
||||
switch gf, ok := snap.GetGlobal(file.Name); {
|
||||
switch gf, ok := snap.GetGlobal(fi.Name); {
|
||||
case !ok:
|
||||
case gf.IsReceiveOnlyChanged():
|
||||
l.Debugln("removing deleted, receive-only item that is globally receive-only from db", file)
|
||||
batch.Remove(file.Name)
|
||||
l.Debugln("removing deleted, receive-only item that is globally receive-only from db", fi)
|
||||
batch.Remove(fi.Name)
|
||||
changes++
|
||||
case gf.IsDeleted():
|
||||
// Our item is deleted and the global item is deleted too. We just
|
||||
// pretend it is a normal deleted file (nobody cares about that).
|
||||
l.Debugf("%v scanning: Marking globally deleted item as not locally changed: %v", f, file.Name)
|
||||
file.LocalFlags &^= protocol.FlagLocalReceiveOnly
|
||||
if batch.Update(file.ConvertDeletedToFileInfo(), snap) {
|
||||
l.Debugf("%v scanning: Marking globally deleted item as not locally changed: %v", f, fi.Name)
|
||||
fi.LocalFlags &^= protocol.FlagLocalReceiveOnly
|
||||
if batch.Update(fi, snap) {
|
||||
changes++
|
||||
}
|
||||
}
|
||||
default:
|
||||
// No need to bump the version for a file that was and is
|
||||
// deleted and just the folder type/local flags changed.
|
||||
file.LocalFlags &^= protocol.FlagLocalReceiveOnly
|
||||
l.Debugln("removing receive-only flag on deleted item", file)
|
||||
if batch.Update(file.ConvertDeletedToFileInfo(), snap) {
|
||||
fi.LocalFlags &^= protocol.FlagLocalReceiveOnly
|
||||
l.Debugln("removing receive-only flag on deleted item", fi)
|
||||
if batch.Update(fi, snap) {
|
||||
changes++
|
||||
}
|
||||
}
|
||||
@@ -835,8 +836,9 @@ func (f *folder) scanSubdirsDeletedAndIgnored(subDirs []string, batch *scanBatch
|
||||
|
||||
if iterError == nil && len(toIgnore) > 0 {
|
||||
for _, file := range toIgnore {
|
||||
l.Debugln("marking file as ignored", f)
|
||||
nf := file.ConvertToIgnoredFileInfo()
|
||||
l.Debugln("marking file as ignored", file)
|
||||
nf := file
|
||||
nf.SetIgnored()
|
||||
if batch.Update(nf, snap) {
|
||||
changes++
|
||||
}
|
||||
@@ -863,9 +865,7 @@ func (f *folder) findRename(snap *db.Snapshot, file protocol.FileInfo, alreadyUs
|
||||
found := false
|
||||
nf := protocol.FileInfo{}
|
||||
|
||||
snap.WithBlocksHash(file.BlocksHash, func(ifi protocol.FileIntf) bool {
|
||||
fi := ifi.(protocol.FileInfo)
|
||||
|
||||
snap.WithBlocksHash(file.BlocksHash, func(fi protocol.FileInfo) bool {
|
||||
select {
|
||||
case <-f.ctx.Done():
|
||||
return false
|
||||
|
||||
@@ -56,26 +56,25 @@ func (f *receiveEncryptedFolder) revert() error {
|
||||
defer snap.Release()
|
||||
var iterErr error
|
||||
var dirs []string
|
||||
snap.WithHaveTruncated(protocol.LocalDeviceID, func(intf protocol.FileIntf) bool {
|
||||
snap.WithHaveTruncated(protocol.LocalDeviceID, func(fi protocol.FileInfo) bool {
|
||||
if iterErr = batch.FlushIfFull(); iterErr != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
fit := intf.(db.FileInfoTruncated)
|
||||
if !fit.IsReceiveOnlyChanged() || intf.IsDeleted() {
|
||||
if !fi.IsReceiveOnlyChanged() || fi.IsDeleted() {
|
||||
return true
|
||||
}
|
||||
|
||||
if fit.IsDirectory() {
|
||||
dirs = append(dirs, fit.Name)
|
||||
if fi.IsDirectory() {
|
||||
dirs = append(dirs, fi.Name)
|
||||
return true
|
||||
}
|
||||
|
||||
if err := f.inWritableDir(f.mtimefs.Remove, fit.Name); err != nil && !fs.IsNotExist(err) {
|
||||
f.newScanError(fit.Name, fmt.Errorf("deleting unexpected item: %w", err))
|
||||
if err := f.inWritableDir(f.mtimefs.Remove, fi.Name); err != nil && !fs.IsNotExist(err) {
|
||||
f.newScanError(fi.Name, fmt.Errorf("deleting unexpected item: %w", err))
|
||||
}
|
||||
|
||||
fi := fit.ConvertToDeletedFileInfo(f.shortID)
|
||||
fi.SetDeleted(f.shortID)
|
||||
// Set version to zero, such that we pull the global version in case
|
||||
// this is a valid filename that was erroneously changed locally.
|
||||
// Should already be zero from scanning, but lets be safe.
|
||||
|
||||
@@ -92,8 +92,7 @@ func (f *receiveOnlyFolder) revert() error {
|
||||
return err
|
||||
}
|
||||
defer snap.Release()
|
||||
snap.WithHave(protocol.LocalDeviceID, func(intf protocol.FileIntf) bool {
|
||||
fi := intf.(protocol.FileInfo)
|
||||
snap.WithHave(protocol.LocalDeviceID, func(fi protocol.FileInfo) bool {
|
||||
if !fi.IsReceiveOnlyChanged() {
|
||||
// We're only interested in files that have changed locally in
|
||||
// receive only mode.
|
||||
@@ -216,7 +215,7 @@ func (q *deleteQueue) flush(snap *db.Snapshot) ([]string, error) {
|
||||
for _, dir := range q.dirs {
|
||||
if err := q.handler.deleteDirOnDisk(dir, snap, q.scanChan); err == nil {
|
||||
deleted = append(deleted, dir)
|
||||
} else if err != nil && firstError == nil {
|
||||
} else if firstError == nil {
|
||||
firstError = err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -391,11 +391,10 @@ func TestRecvOnlyRemoteUndoChanges(t *testing.T) {
|
||||
|
||||
files := make([]protocol.FileInfo, 0, 2)
|
||||
snap := fsetSnapshot(t, f.fset)
|
||||
snap.WithHave(protocol.LocalDeviceID, func(fi protocol.FileIntf) bool {
|
||||
if n := fi.FileName(); n != file && n != knownFile {
|
||||
snap.WithHave(protocol.LocalDeviceID, func(f protocol.FileInfo) bool {
|
||||
if f.Name != file && f.Name != knownFile {
|
||||
return true
|
||||
}
|
||||
f := fi.(protocol.FileInfo)
|
||||
f.LocalFlags = 0
|
||||
f.Version = protocol.Vector{}.Update(device1.Short())
|
||||
files = append(files, f)
|
||||
@@ -576,7 +575,7 @@ func setupKnownFiles(t *testing.T, ffs fs.Filesystem, data []byte) []protocol.Fi
|
||||
Permissions: 0o644,
|
||||
Size: fi.Size(),
|
||||
ModifiedS: fi.ModTime().Unix(),
|
||||
ModifiedNs: int(fi.ModTime().UnixNano() % 1e9),
|
||||
ModifiedNs: int32(fi.ModTime().Nanosecond()),
|
||||
Version: protocol.Vector{Counters: []protocol.Counter{{ID: 42, Value: 42}}},
|
||||
Sequence: 42,
|
||||
Blocks: blocks,
|
||||
|
||||
@@ -48,24 +48,22 @@ func (f *sendOnlyFolder) pull() (bool, error) {
|
||||
return false, err
|
||||
}
|
||||
defer snap.Release()
|
||||
snap.WithNeed(protocol.LocalDeviceID, func(intf protocol.FileIntf) bool {
|
||||
snap.WithNeed(protocol.LocalDeviceID, func(file protocol.FileInfo) bool {
|
||||
batch.FlushIfFull()
|
||||
|
||||
file := intf.(protocol.FileInfo)
|
||||
|
||||
if f.ignores.Match(intf.FileName()).IsIgnored() {
|
||||
if f.ignores.Match(file.FileName()).IsIgnored() {
|
||||
file.SetIgnored()
|
||||
batch.Append(file)
|
||||
l.Debugln(f, "Handling ignored file", file)
|
||||
return true
|
||||
}
|
||||
|
||||
curFile, ok := snap.Get(protocol.LocalDeviceID, intf.FileName())
|
||||
curFile, ok := snap.Get(protocol.LocalDeviceID, file.FileName())
|
||||
if !ok {
|
||||
if intf.IsInvalid() {
|
||||
if file.IsInvalid() {
|
||||
// Global invalid file just exists for need accounting
|
||||
batch.Append(file)
|
||||
} else if intf.IsDeleted() {
|
||||
} else if file.IsDeleted() {
|
||||
l.Debugln("Should never get a deleted file as needed when we don't have it")
|
||||
f.evLogger.Log(events.Failure, "got deleted file that doesn't exist locally as needed when pulling on send-only")
|
||||
}
|
||||
@@ -111,8 +109,7 @@ func (f *sendOnlyFolder) override() error {
|
||||
return err
|
||||
}
|
||||
defer snap.Release()
|
||||
snap.WithNeed(protocol.LocalDeviceID, func(fi protocol.FileIntf) bool {
|
||||
need := fi.(protocol.FileInfo)
|
||||
snap.WithNeed(protocol.LocalDeviceID, func(need protocol.FileInfo) bool {
|
||||
_ = batch.FlushIfFull()
|
||||
|
||||
have, ok := snap.Get(protocol.LocalDeviceID, need.Name)
|
||||
|
||||
@@ -326,22 +326,20 @@ func (f *sendReceiveFolder) processNeeded(snap *db.Snapshot, dbUpdateChan chan<-
|
||||
// Regular files to pull goes into the file queue, everything else
|
||||
// (directories, symlinks and deletes) goes into the "process directly"
|
||||
// pile.
|
||||
snap.WithNeed(protocol.LocalDeviceID, func(intf protocol.FileIntf) bool {
|
||||
snap.WithNeed(protocol.LocalDeviceID, func(file protocol.FileInfo) bool {
|
||||
select {
|
||||
case <-f.ctx.Done():
|
||||
return false
|
||||
default:
|
||||
}
|
||||
|
||||
if f.IgnoreDelete && intf.IsDeleted() {
|
||||
l.Debugln(f, "ignore file deletion (config)", intf.FileName())
|
||||
if f.IgnoreDelete && file.IsDeleted() {
|
||||
l.Debugln(f, "ignore file deletion (config)", file.FileName())
|
||||
return true
|
||||
}
|
||||
|
||||
changed++
|
||||
|
||||
file := intf.(protocol.FileInfo)
|
||||
|
||||
switch {
|
||||
case f.ignores.Match(file.Name).IsIgnored():
|
||||
file.SetIgnored()
|
||||
@@ -1021,13 +1019,13 @@ func (f *sendReceiveFolder) renameFile(cur, source, target protocol.FileInfo, sn
|
||||
if f.versioner != nil {
|
||||
err = f.CheckAvailableSpace(uint64(source.Size))
|
||||
if err == nil {
|
||||
err = osutil.Copy(f.CopyRangeMethod, f.mtimefs, f.mtimefs, source.Name, tempName)
|
||||
err = osutil.Copy(f.CopyRangeMethod.ToFS(), f.mtimefs, f.mtimefs, source.Name, tempName)
|
||||
if err == nil {
|
||||
err = f.inWritableDir(f.versioner.Archive, source.Name)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err = osutil.RenameOrCopy(f.CopyRangeMethod, f.mtimefs, f.mtimefs, source.Name, tempName)
|
||||
err = osutil.RenameOrCopy(f.CopyRangeMethod.ToFS(), f.mtimefs, f.mtimefs, source.Name, tempName)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -1387,11 +1385,11 @@ func (f *sendReceiveFolder) copierRoutine(in <-chan copyBlocksState, pullChan ch
|
||||
}
|
||||
}
|
||||
|
||||
if f.CopyRangeMethod != fs.CopyRangeMethodStandard {
|
||||
if f.CopyRangeMethod != config.CopyRangeMethodStandard {
|
||||
err = f.withLimiter(func() error {
|
||||
dstFd.mut.Lock()
|
||||
defer dstFd.mut.Unlock()
|
||||
return fs.CopyRange(f.CopyRangeMethod, fd, dstFd.fd, srcOffset, block.Offset, int64(block.Size))
|
||||
return fs.CopyRange(f.CopyRangeMethod.ToFS(), fd, dstFd.fd, srcOffset, block.Offset, int64(block.Size))
|
||||
})
|
||||
} else {
|
||||
err = f.limitedWriteAt(dstFd, buf, block.Offset)
|
||||
@@ -1651,7 +1649,7 @@ func (f *sendReceiveFolder) performFinish(file, curFile protocol.FileInfo, hasCu
|
||||
|
||||
// Replace the original content with the new one. If it didn't work,
|
||||
// leave the temp file in place for reuse.
|
||||
if err := osutil.RenameOrCopy(f.CopyRangeMethod, f.mtimefs, f.mtimefs, tempName, file.Name); err != nil {
|
||||
if err := osutil.RenameOrCopy(f.CopyRangeMethod.ToFS(), f.mtimefs, f.mtimefs, tempName, file.Name); err != nil {
|
||||
return fmt.Errorf("replacing file: %w", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -363,7 +363,7 @@ func TestWeakHash(t *testing.T) {
|
||||
Blocks: existing,
|
||||
Size: size,
|
||||
ModifiedS: info.ModTime().Unix(),
|
||||
ModifiedNs: info.ModTime().Nanosecond(),
|
||||
ModifiedNs: int32(info.ModTime().Nanosecond()),
|
||||
}
|
||||
desiredFile := protocol.FileInfo{
|
||||
Name: "weakhash",
|
||||
@@ -812,7 +812,7 @@ func TestCopyOwner(t *testing.T) {
|
||||
|
||||
m, f, wcfgCancel := setupSendReceiveFolder(t)
|
||||
defer wcfgCancel()
|
||||
f.folder.FolderConfiguration = newFolderConfiguration(m.cfg, f.ID, f.Label, fs.FilesystemTypeFake, "/TestCopyOwner")
|
||||
f.folder.FolderConfiguration = newFolderConfiguration(m.cfg, f.ID, f.Label, config.FilesystemTypeFake, "/TestCopyOwner")
|
||||
f.folder.FolderConfiguration.CopyOwnershipFromParent = true
|
||||
|
||||
f.fset = newFileSet(t, f.ID, m.db)
|
||||
@@ -1101,11 +1101,11 @@ func TestPullCaseOnlyPerformFinish(t *testing.T) {
|
||||
hasCur := false
|
||||
snap := dbSnapshot(t, m, f.ID)
|
||||
defer snap.Release()
|
||||
snap.WithHave(protocol.LocalDeviceID, func(i protocol.FileIntf) bool {
|
||||
snap.WithHave(protocol.LocalDeviceID, func(i protocol.FileInfo) bool {
|
||||
if hasCur {
|
||||
t.Fatal("got more than one file")
|
||||
}
|
||||
cur = i.(protocol.FileInfo)
|
||||
cur = i
|
||||
hasCur = true
|
||||
return true
|
||||
})
|
||||
@@ -1166,11 +1166,11 @@ func testPullCaseOnlyDirOrSymlink(t *testing.T, dir bool) {
|
||||
hasCur := false
|
||||
snap := dbSnapshot(t, m, f.ID)
|
||||
defer snap.Release()
|
||||
snap.WithHave(protocol.LocalDeviceID, func(i protocol.FileIntf) bool {
|
||||
snap.WithHave(protocol.LocalDeviceID, func(i protocol.FileInfo) bool {
|
||||
if hasCur {
|
||||
t.Fatal("got more than one file")
|
||||
}
|
||||
cur = i.(protocol.FileInfo)
|
||||
cur = i
|
||||
hasCur = true
|
||||
return true
|
||||
})
|
||||
|
||||
@@ -292,7 +292,7 @@ func (s *indexHandler) sendIndexTo(ctx context.Context, fset *db.FileSet) error
|
||||
}
|
||||
defer snap.Release()
|
||||
previousWasDelete := false
|
||||
snap.WithHaveSequence(s.localPrevSequence+1, func(fi protocol.FileIntf) bool {
|
||||
snap.WithHaveSequence(s.localPrevSequence+1, func(fi protocol.FileInfo) bool {
|
||||
// This is to make sure that renames (which is an add followed by a delete) land in the same batch.
|
||||
// Even if the batch is full, we allow a last delete to slip in, we do this by making sure that
|
||||
// the batch ends with a non-delete, or that the last item in the batch is already a delete
|
||||
@@ -329,7 +329,7 @@ func (s *indexHandler) sendIndexTo(ctx context.Context, fset *db.FileSet) error
|
||||
return false
|
||||
}
|
||||
|
||||
f = fi.(protocol.FileInfo)
|
||||
f = fi
|
||||
|
||||
// If this is a folder receiving encrypted files only, we
|
||||
// mustn't ever send locally changed file infos. Those aren't
|
||||
|
||||
@@ -9,10 +9,6 @@ import (
|
||||
)
|
||||
|
||||
type FolderSummaryService struct {
|
||||
OnEventRequestStub func()
|
||||
onEventRequestMutex sync.RWMutex
|
||||
onEventRequestArgsForCall []struct {
|
||||
}
|
||||
ServeStub func(context.Context) error
|
||||
serveMutex sync.RWMutex
|
||||
serveArgsForCall []struct {
|
||||
@@ -41,30 +37,6 @@ type FolderSummaryService struct {
|
||||
invocationsMutex sync.RWMutex
|
||||
}
|
||||
|
||||
func (fake *FolderSummaryService) OnEventRequest() {
|
||||
fake.onEventRequestMutex.Lock()
|
||||
fake.onEventRequestArgsForCall = append(fake.onEventRequestArgsForCall, struct {
|
||||
}{})
|
||||
stub := fake.OnEventRequestStub
|
||||
fake.recordInvocation("OnEventRequest", []interface{}{})
|
||||
fake.onEventRequestMutex.Unlock()
|
||||
if stub != nil {
|
||||
fake.OnEventRequestStub()
|
||||
}
|
||||
}
|
||||
|
||||
func (fake *FolderSummaryService) OnEventRequestCallCount() int {
|
||||
fake.onEventRequestMutex.RLock()
|
||||
defer fake.onEventRequestMutex.RUnlock()
|
||||
return len(fake.onEventRequestArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *FolderSummaryService) OnEventRequestCalls(stub func()) {
|
||||
fake.onEventRequestMutex.Lock()
|
||||
defer fake.onEventRequestMutex.Unlock()
|
||||
fake.OnEventRequestStub = stub
|
||||
}
|
||||
|
||||
func (fake *FolderSummaryService) Serve(arg1 context.Context) error {
|
||||
fake.serveMutex.Lock()
|
||||
ret, specificReturn := fake.serveReturnsOnCall[len(fake.serveArgsForCall)]
|
||||
@@ -193,8 +165,6 @@ func (fake *FolderSummaryService) SummaryReturnsOnCall(i int, result1 *model.Fol
|
||||
func (fake *FolderSummaryService) Invocations() map[string][][]interface{} {
|
||||
fake.invocationsMutex.RLock()
|
||||
defer fake.invocationsMutex.RUnlock()
|
||||
fake.onEventRequestMutex.RLock()
|
||||
defer fake.onEventRequestMutex.RUnlock()
|
||||
fake.serveMutex.RLock()
|
||||
defer fake.serveMutex.RUnlock()
|
||||
fake.summaryMutex.RLock()
|
||||
|
||||
+40
-40
@@ -328,7 +328,7 @@ type Model struct {
|
||||
result2 []string
|
||||
result3 error
|
||||
}
|
||||
LocalChangedFolderFilesStub func(string, int, int) ([]db.FileInfoTruncated, error)
|
||||
LocalChangedFolderFilesStub func(string, int, int) ([]protocol.FileInfo, error)
|
||||
localChangedFolderFilesMutex sync.RWMutex
|
||||
localChangedFolderFilesArgsForCall []struct {
|
||||
arg1 string
|
||||
@@ -336,14 +336,14 @@ type Model struct {
|
||||
arg3 int
|
||||
}
|
||||
localChangedFolderFilesReturns struct {
|
||||
result1 []db.FileInfoTruncated
|
||||
result1 []protocol.FileInfo
|
||||
result2 error
|
||||
}
|
||||
localChangedFolderFilesReturnsOnCall map[int]struct {
|
||||
result1 []db.FileInfoTruncated
|
||||
result1 []protocol.FileInfo
|
||||
result2 error
|
||||
}
|
||||
NeedFolderFilesStub func(string, int, int) ([]db.FileInfoTruncated, []db.FileInfoTruncated, []db.FileInfoTruncated, error)
|
||||
NeedFolderFilesStub func(string, int, int) ([]protocol.FileInfo, []protocol.FileInfo, []protocol.FileInfo, error)
|
||||
needFolderFilesMutex sync.RWMutex
|
||||
needFolderFilesArgsForCall []struct {
|
||||
arg1 string
|
||||
@@ -351,15 +351,15 @@ type Model struct {
|
||||
arg3 int
|
||||
}
|
||||
needFolderFilesReturns struct {
|
||||
result1 []db.FileInfoTruncated
|
||||
result2 []db.FileInfoTruncated
|
||||
result3 []db.FileInfoTruncated
|
||||
result1 []protocol.FileInfo
|
||||
result2 []protocol.FileInfo
|
||||
result3 []protocol.FileInfo
|
||||
result4 error
|
||||
}
|
||||
needFolderFilesReturnsOnCall map[int]struct {
|
||||
result1 []db.FileInfoTruncated
|
||||
result2 []db.FileInfoTruncated
|
||||
result3 []db.FileInfoTruncated
|
||||
result1 []protocol.FileInfo
|
||||
result2 []protocol.FileInfo
|
||||
result3 []protocol.FileInfo
|
||||
result4 error
|
||||
}
|
||||
OnHelloStub func(protocol.DeviceID, net.Addr, protocol.Hello) error
|
||||
@@ -405,7 +405,7 @@ type Model struct {
|
||||
result1 map[string]db.PendingFolder
|
||||
result2 error
|
||||
}
|
||||
RemoteNeedFolderFilesStub func(string, protocol.DeviceID, int, int) ([]db.FileInfoTruncated, error)
|
||||
RemoteNeedFolderFilesStub func(string, protocol.DeviceID, int, int) ([]protocol.FileInfo, error)
|
||||
remoteNeedFolderFilesMutex sync.RWMutex
|
||||
remoteNeedFolderFilesArgsForCall []struct {
|
||||
arg1 string
|
||||
@@ -414,11 +414,11 @@ type Model struct {
|
||||
arg4 int
|
||||
}
|
||||
remoteNeedFolderFilesReturns struct {
|
||||
result1 []db.FileInfoTruncated
|
||||
result1 []protocol.FileInfo
|
||||
result2 error
|
||||
}
|
||||
remoteNeedFolderFilesReturnsOnCall map[int]struct {
|
||||
result1 []db.FileInfoTruncated
|
||||
result1 []protocol.FileInfo
|
||||
result2 error
|
||||
}
|
||||
RequestStub func(protocol.Connection, *protocol.Request) (protocol.RequestResponse, error)
|
||||
@@ -2095,7 +2095,7 @@ func (fake *Model) LoadIgnoresReturnsOnCall(i int, result1 []string, result2 []s
|
||||
}{result1, result2, result3}
|
||||
}
|
||||
|
||||
func (fake *Model) LocalChangedFolderFiles(arg1 string, arg2 int, arg3 int) ([]db.FileInfoTruncated, error) {
|
||||
func (fake *Model) LocalChangedFolderFiles(arg1 string, arg2 int, arg3 int) ([]protocol.FileInfo, error) {
|
||||
fake.localChangedFolderFilesMutex.Lock()
|
||||
ret, specificReturn := fake.localChangedFolderFilesReturnsOnCall[len(fake.localChangedFolderFilesArgsForCall)]
|
||||
fake.localChangedFolderFilesArgsForCall = append(fake.localChangedFolderFilesArgsForCall, struct {
|
||||
@@ -2122,7 +2122,7 @@ func (fake *Model) LocalChangedFolderFilesCallCount() int {
|
||||
return len(fake.localChangedFolderFilesArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *Model) LocalChangedFolderFilesCalls(stub func(string, int, int) ([]db.FileInfoTruncated, error)) {
|
||||
func (fake *Model) LocalChangedFolderFilesCalls(stub func(string, int, int) ([]protocol.FileInfo, error)) {
|
||||
fake.localChangedFolderFilesMutex.Lock()
|
||||
defer fake.localChangedFolderFilesMutex.Unlock()
|
||||
fake.LocalChangedFolderFilesStub = stub
|
||||
@@ -2135,33 +2135,33 @@ func (fake *Model) LocalChangedFolderFilesArgsForCall(i int) (string, int, int)
|
||||
return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3
|
||||
}
|
||||
|
||||
func (fake *Model) LocalChangedFolderFilesReturns(result1 []db.FileInfoTruncated, result2 error) {
|
||||
func (fake *Model) LocalChangedFolderFilesReturns(result1 []protocol.FileInfo, result2 error) {
|
||||
fake.localChangedFolderFilesMutex.Lock()
|
||||
defer fake.localChangedFolderFilesMutex.Unlock()
|
||||
fake.LocalChangedFolderFilesStub = nil
|
||||
fake.localChangedFolderFilesReturns = struct {
|
||||
result1 []db.FileInfoTruncated
|
||||
result1 []protocol.FileInfo
|
||||
result2 error
|
||||
}{result1, result2}
|
||||
}
|
||||
|
||||
func (fake *Model) LocalChangedFolderFilesReturnsOnCall(i int, result1 []db.FileInfoTruncated, result2 error) {
|
||||
func (fake *Model) LocalChangedFolderFilesReturnsOnCall(i int, result1 []protocol.FileInfo, result2 error) {
|
||||
fake.localChangedFolderFilesMutex.Lock()
|
||||
defer fake.localChangedFolderFilesMutex.Unlock()
|
||||
fake.LocalChangedFolderFilesStub = nil
|
||||
if fake.localChangedFolderFilesReturnsOnCall == nil {
|
||||
fake.localChangedFolderFilesReturnsOnCall = make(map[int]struct {
|
||||
result1 []db.FileInfoTruncated
|
||||
result1 []protocol.FileInfo
|
||||
result2 error
|
||||
})
|
||||
}
|
||||
fake.localChangedFolderFilesReturnsOnCall[i] = struct {
|
||||
result1 []db.FileInfoTruncated
|
||||
result1 []protocol.FileInfo
|
||||
result2 error
|
||||
}{result1, result2}
|
||||
}
|
||||
|
||||
func (fake *Model) NeedFolderFiles(arg1 string, arg2 int, arg3 int) ([]db.FileInfoTruncated, []db.FileInfoTruncated, []db.FileInfoTruncated, error) {
|
||||
func (fake *Model) NeedFolderFiles(arg1 string, arg2 int, arg3 int) ([]protocol.FileInfo, []protocol.FileInfo, []protocol.FileInfo, error) {
|
||||
fake.needFolderFilesMutex.Lock()
|
||||
ret, specificReturn := fake.needFolderFilesReturnsOnCall[len(fake.needFolderFilesArgsForCall)]
|
||||
fake.needFolderFilesArgsForCall = append(fake.needFolderFilesArgsForCall, struct {
|
||||
@@ -2188,7 +2188,7 @@ func (fake *Model) NeedFolderFilesCallCount() int {
|
||||
return len(fake.needFolderFilesArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *Model) NeedFolderFilesCalls(stub func(string, int, int) ([]db.FileInfoTruncated, []db.FileInfoTruncated, []db.FileInfoTruncated, error)) {
|
||||
func (fake *Model) NeedFolderFilesCalls(stub func(string, int, int) ([]protocol.FileInfo, []protocol.FileInfo, []protocol.FileInfo, error)) {
|
||||
fake.needFolderFilesMutex.Lock()
|
||||
defer fake.needFolderFilesMutex.Unlock()
|
||||
fake.NeedFolderFilesStub = stub
|
||||
@@ -2201,34 +2201,34 @@ func (fake *Model) NeedFolderFilesArgsForCall(i int) (string, int, int) {
|
||||
return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3
|
||||
}
|
||||
|
||||
func (fake *Model) NeedFolderFilesReturns(result1 []db.FileInfoTruncated, result2 []db.FileInfoTruncated, result3 []db.FileInfoTruncated, result4 error) {
|
||||
func (fake *Model) NeedFolderFilesReturns(result1 []protocol.FileInfo, result2 []protocol.FileInfo, result3 []protocol.FileInfo, result4 error) {
|
||||
fake.needFolderFilesMutex.Lock()
|
||||
defer fake.needFolderFilesMutex.Unlock()
|
||||
fake.NeedFolderFilesStub = nil
|
||||
fake.needFolderFilesReturns = struct {
|
||||
result1 []db.FileInfoTruncated
|
||||
result2 []db.FileInfoTruncated
|
||||
result3 []db.FileInfoTruncated
|
||||
result1 []protocol.FileInfo
|
||||
result2 []protocol.FileInfo
|
||||
result3 []protocol.FileInfo
|
||||
result4 error
|
||||
}{result1, result2, result3, result4}
|
||||
}
|
||||
|
||||
func (fake *Model) NeedFolderFilesReturnsOnCall(i int, result1 []db.FileInfoTruncated, result2 []db.FileInfoTruncated, result3 []db.FileInfoTruncated, result4 error) {
|
||||
func (fake *Model) NeedFolderFilesReturnsOnCall(i int, result1 []protocol.FileInfo, result2 []protocol.FileInfo, result3 []protocol.FileInfo, result4 error) {
|
||||
fake.needFolderFilesMutex.Lock()
|
||||
defer fake.needFolderFilesMutex.Unlock()
|
||||
fake.NeedFolderFilesStub = nil
|
||||
if fake.needFolderFilesReturnsOnCall == nil {
|
||||
fake.needFolderFilesReturnsOnCall = make(map[int]struct {
|
||||
result1 []db.FileInfoTruncated
|
||||
result2 []db.FileInfoTruncated
|
||||
result3 []db.FileInfoTruncated
|
||||
result1 []protocol.FileInfo
|
||||
result2 []protocol.FileInfo
|
||||
result3 []protocol.FileInfo
|
||||
result4 error
|
||||
})
|
||||
}
|
||||
fake.needFolderFilesReturnsOnCall[i] = struct {
|
||||
result1 []db.FileInfoTruncated
|
||||
result2 []db.FileInfoTruncated
|
||||
result3 []db.FileInfoTruncated
|
||||
result1 []protocol.FileInfo
|
||||
result2 []protocol.FileInfo
|
||||
result3 []protocol.FileInfo
|
||||
result4 error
|
||||
}{result1, result2, result3, result4}
|
||||
}
|
||||
@@ -2448,7 +2448,7 @@ func (fake *Model) PendingFoldersReturnsOnCall(i int, result1 map[string]db.Pend
|
||||
}{result1, result2}
|
||||
}
|
||||
|
||||
func (fake *Model) RemoteNeedFolderFiles(arg1 string, arg2 protocol.DeviceID, arg3 int, arg4 int) ([]db.FileInfoTruncated, error) {
|
||||
func (fake *Model) RemoteNeedFolderFiles(arg1 string, arg2 protocol.DeviceID, arg3 int, arg4 int) ([]protocol.FileInfo, error) {
|
||||
fake.remoteNeedFolderFilesMutex.Lock()
|
||||
ret, specificReturn := fake.remoteNeedFolderFilesReturnsOnCall[len(fake.remoteNeedFolderFilesArgsForCall)]
|
||||
fake.remoteNeedFolderFilesArgsForCall = append(fake.remoteNeedFolderFilesArgsForCall, struct {
|
||||
@@ -2476,7 +2476,7 @@ func (fake *Model) RemoteNeedFolderFilesCallCount() int {
|
||||
return len(fake.remoteNeedFolderFilesArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *Model) RemoteNeedFolderFilesCalls(stub func(string, protocol.DeviceID, int, int) ([]db.FileInfoTruncated, error)) {
|
||||
func (fake *Model) RemoteNeedFolderFilesCalls(stub func(string, protocol.DeviceID, int, int) ([]protocol.FileInfo, error)) {
|
||||
fake.remoteNeedFolderFilesMutex.Lock()
|
||||
defer fake.remoteNeedFolderFilesMutex.Unlock()
|
||||
fake.RemoteNeedFolderFilesStub = stub
|
||||
@@ -2489,28 +2489,28 @@ func (fake *Model) RemoteNeedFolderFilesArgsForCall(i int) (string, protocol.Dev
|
||||
return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3, argsForCall.arg4
|
||||
}
|
||||
|
||||
func (fake *Model) RemoteNeedFolderFilesReturns(result1 []db.FileInfoTruncated, result2 error) {
|
||||
func (fake *Model) RemoteNeedFolderFilesReturns(result1 []protocol.FileInfo, result2 error) {
|
||||
fake.remoteNeedFolderFilesMutex.Lock()
|
||||
defer fake.remoteNeedFolderFilesMutex.Unlock()
|
||||
fake.RemoteNeedFolderFilesStub = nil
|
||||
fake.remoteNeedFolderFilesReturns = struct {
|
||||
result1 []db.FileInfoTruncated
|
||||
result1 []protocol.FileInfo
|
||||
result2 error
|
||||
}{result1, result2}
|
||||
}
|
||||
|
||||
func (fake *Model) RemoteNeedFolderFilesReturnsOnCall(i int, result1 []db.FileInfoTruncated, result2 error) {
|
||||
func (fake *Model) RemoteNeedFolderFilesReturnsOnCall(i int, result1 []protocol.FileInfo, result2 error) {
|
||||
fake.remoteNeedFolderFilesMutex.Lock()
|
||||
defer fake.remoteNeedFolderFilesMutex.Unlock()
|
||||
fake.RemoteNeedFolderFilesStub = nil
|
||||
if fake.remoteNeedFolderFilesReturnsOnCall == nil {
|
||||
fake.remoteNeedFolderFilesReturnsOnCall = make(map[int]struct {
|
||||
result1 []db.FileInfoTruncated
|
||||
result1 []protocol.FileInfo
|
||||
result2 error
|
||||
})
|
||||
}
|
||||
fake.remoteNeedFolderFilesReturnsOnCall[i] = struct {
|
||||
result1 []db.FileInfoTruncated
|
||||
result1 []protocol.FileInfo
|
||||
result2 error
|
||||
}{result1, result2}
|
||||
}
|
||||
|
||||
+24
-28
@@ -94,9 +94,9 @@ type Model interface {
|
||||
RestoreFolderVersions(folder string, versions map[string]time.Time) (map[string]error, error)
|
||||
|
||||
DBSnapshot(folder string) (*db.Snapshot, error)
|
||||
NeedFolderFiles(folder string, page, perpage int) ([]db.FileInfoTruncated, []db.FileInfoTruncated, []db.FileInfoTruncated, error)
|
||||
RemoteNeedFolderFiles(folder string, device protocol.DeviceID, page, perpage int) ([]db.FileInfoTruncated, error)
|
||||
LocalChangedFolderFiles(folder string, page, perpage int) ([]db.FileInfoTruncated, error)
|
||||
NeedFolderFiles(folder string, page, perpage int) ([]protocol.FileInfo, []protocol.FileInfo, []protocol.FileInfo, error)
|
||||
RemoteNeedFolderFiles(folder string, device protocol.DeviceID, page, perpage int) ([]protocol.FileInfo, error)
|
||||
LocalChangedFolderFiles(folder string, page, perpage int) ([]protocol.FileInfo, error)
|
||||
FolderProgressBytesCompleted(folder string) int64
|
||||
|
||||
CurrentFolderFile(folder string, file string) (protocol.FileInfo, bool, error)
|
||||
@@ -944,7 +944,7 @@ func (m *model) folderCompletion(device protocol.DeviceID, folder string) (Folde
|
||||
|
||||
need := snap.NeedSize(device)
|
||||
need.Bytes -= downloaded
|
||||
// This might might be more than it really is, because some blocks can be of a smaller size.
|
||||
// This might be more than it really is, because some blocks can be of a smaller size.
|
||||
if need.Bytes < 0 {
|
||||
need.Bytes = 0
|
||||
}
|
||||
@@ -973,7 +973,7 @@ func (m *model) FolderProgressBytesCompleted(folder string) int64 {
|
||||
|
||||
// NeedFolderFiles returns paginated list of currently needed files in
|
||||
// progress, queued, and to be queued on next puller iteration.
|
||||
func (m *model) NeedFolderFiles(folder string, page, perpage int) ([]db.FileInfoTruncated, []db.FileInfoTruncated, []db.FileInfoTruncated, error) {
|
||||
func (m *model) NeedFolderFiles(folder string, page, perpage int) ([]protocol.FileInfo, []protocol.FileInfo, []protocol.FileInfo, error) {
|
||||
m.mut.RLock()
|
||||
rf, rfOk := m.folderFiles[folder]
|
||||
runner, runnerOk := m.folderRunners.Get(folder)
|
||||
@@ -989,7 +989,7 @@ func (m *model) NeedFolderFiles(folder string, page, perpage int) ([]db.FileInfo
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
defer snap.Release()
|
||||
var progress, queued, rest []db.FileInfoTruncated
|
||||
var progress, queued, rest []protocol.FileInfo
|
||||
var seen map[string]struct{}
|
||||
|
||||
p := newPager(page, perpage)
|
||||
@@ -997,8 +997,8 @@ func (m *model) NeedFolderFiles(folder string, page, perpage int) ([]db.FileInfo
|
||||
if runnerOk {
|
||||
progressNames, queuedNames, skipped := runner.Jobs(page, perpage)
|
||||
|
||||
progress = make([]db.FileInfoTruncated, len(progressNames))
|
||||
queued = make([]db.FileInfoTruncated, len(queuedNames))
|
||||
progress = make([]protocol.FileInfo, len(progressNames))
|
||||
queued = make([]protocol.FileInfo, len(queuedNames))
|
||||
seen = make(map[string]struct{}, len(progressNames)+len(queuedNames))
|
||||
|
||||
for i, name := range progressNames {
|
||||
@@ -1022,8 +1022,8 @@ func (m *model) NeedFolderFiles(folder string, page, perpage int) ([]db.FileInfo
|
||||
p.toSkip -= skipped
|
||||
}
|
||||
|
||||
rest = make([]db.FileInfoTruncated, 0, perpage)
|
||||
snap.WithNeedTruncated(protocol.LocalDeviceID, func(f protocol.FileIntf) bool {
|
||||
rest = make([]protocol.FileInfo, 0, perpage)
|
||||
snap.WithNeedTruncated(protocol.LocalDeviceID, func(f protocol.FileInfo) bool {
|
||||
if cfg.IgnoreDelete && f.IsDeleted() {
|
||||
return true
|
||||
}
|
||||
@@ -1031,9 +1031,8 @@ func (m *model) NeedFolderFiles(folder string, page, perpage int) ([]db.FileInfo
|
||||
if p.skip() {
|
||||
return true
|
||||
}
|
||||
ft := f.(db.FileInfoTruncated)
|
||||
if _, ok := seen[ft.Name]; !ok {
|
||||
rest = append(rest, ft)
|
||||
if _, ok := seen[f.Name]; !ok {
|
||||
rest = append(rest, f)
|
||||
p.get--
|
||||
}
|
||||
return p.get > 0
|
||||
@@ -1044,7 +1043,7 @@ func (m *model) NeedFolderFiles(folder string, page, perpage int) ([]db.FileInfo
|
||||
|
||||
// RemoteNeedFolderFiles returns paginated list of currently needed files for a
|
||||
// remote device to become synced with a folder.
|
||||
func (m *model) RemoteNeedFolderFiles(folder string, device protocol.DeviceID, page, perpage int) ([]db.FileInfoTruncated, error) {
|
||||
func (m *model) RemoteNeedFolderFiles(folder string, device protocol.DeviceID, page, perpage int) ([]protocol.FileInfo, error) {
|
||||
m.mut.RLock()
|
||||
rf, ok := m.folderFiles[folder]
|
||||
m.mut.RUnlock()
|
||||
@@ -1059,19 +1058,19 @@ func (m *model) RemoteNeedFolderFiles(folder string, device protocol.DeviceID, p
|
||||
}
|
||||
defer snap.Release()
|
||||
|
||||
files := make([]db.FileInfoTruncated, 0, perpage)
|
||||
files := make([]protocol.FileInfo, 0, perpage)
|
||||
p := newPager(page, perpage)
|
||||
snap.WithNeedTruncated(device, func(f protocol.FileIntf) bool {
|
||||
snap.WithNeedTruncated(device, func(f protocol.FileInfo) bool {
|
||||
if p.skip() {
|
||||
return true
|
||||
}
|
||||
files = append(files, f.(db.FileInfoTruncated))
|
||||
files = append(files, f)
|
||||
return !p.done()
|
||||
})
|
||||
return files, nil
|
||||
}
|
||||
|
||||
func (m *model) LocalChangedFolderFiles(folder string, page, perpage int) ([]db.FileInfoTruncated, error) {
|
||||
func (m *model) LocalChangedFolderFiles(folder string, page, perpage int) ([]protocol.FileInfo, error) {
|
||||
m.mut.RLock()
|
||||
rf, ok := m.folderFiles[folder]
|
||||
m.mut.RUnlock()
|
||||
@@ -1091,17 +1090,16 @@ func (m *model) LocalChangedFolderFiles(folder string, page, perpage int) ([]db.
|
||||
}
|
||||
|
||||
p := newPager(page, perpage)
|
||||
files := make([]db.FileInfoTruncated, 0, perpage)
|
||||
files := make([]protocol.FileInfo, 0, perpage)
|
||||
|
||||
snap.WithHaveTruncated(protocol.LocalDeviceID, func(f protocol.FileIntf) bool {
|
||||
snap.WithHaveTruncated(protocol.LocalDeviceID, func(f protocol.FileInfo) bool {
|
||||
if !f.IsReceiveOnlyChanged() {
|
||||
return true
|
||||
}
|
||||
if p.skip() {
|
||||
return true
|
||||
}
|
||||
ft := f.(db.FileInfoTruncated)
|
||||
files = append(files, ft)
|
||||
files = append(files, f)
|
||||
return !p.done()
|
||||
})
|
||||
|
||||
@@ -1751,7 +1749,7 @@ func (*model) handleDeintroductions(introducerCfg config.DeviceConfiguration, fo
|
||||
// AutoAcceptFolders set to true.
|
||||
func (m *model) handleAutoAccepts(deviceID protocol.DeviceID, folder protocol.Folder, ccDeviceInfos *clusterConfigDeviceInfo, cfg config.FolderConfiguration, haveCfg bool, defaultFolderCfg config.FolderConfiguration) (config.FolderConfiguration, bool) {
|
||||
if !haveCfg {
|
||||
defaultPathFs := fs.NewFilesystem(defaultFolderCfg.FilesystemType, defaultFolderCfg.Path)
|
||||
defaultPathFs := fs.NewFilesystem(defaultFolderCfg.FilesystemType.ToFS(), defaultFolderCfg.Path)
|
||||
var pathAlternatives []string
|
||||
if alt := fs.SanitizePath(folder.Label); alt != "" {
|
||||
pathAlternatives = append(pathAlternatives, alt)
|
||||
@@ -2634,7 +2632,7 @@ func (m *model) generateClusterConfigRLocked(device protocol.DeviceID) (*protoco
|
||||
ID: deviceCfg.DeviceID,
|
||||
Name: deviceCfg.Name,
|
||||
Addresses: deviceCfg.Addresses,
|
||||
Compression: deviceCfg.Compression,
|
||||
Compression: deviceCfg.Compression.ToProtocol(),
|
||||
CertName: deviceCfg.CertName,
|
||||
Introducer: deviceCfg.Introducer,
|
||||
}
|
||||
@@ -2773,9 +2771,7 @@ func (m *model) GlobalDirectoryTree(folder, prefix string, levels int, dirsOnly
|
||||
return nil, err
|
||||
}
|
||||
defer snap.Release()
|
||||
snap.WithPrefixedGlobalTruncated(prefix, func(fi protocol.FileIntf) bool {
|
||||
f := fi.(db.FileInfoTruncated)
|
||||
|
||||
snap.WithPrefixedGlobalTruncated(prefix, func(f protocol.FileInfo) bool {
|
||||
// Don't include the prefix itself.
|
||||
if f.IsInvalid() || f.IsDeleted() || strings.HasPrefix(prefix, f.Name) {
|
||||
return true
|
||||
@@ -3471,7 +3467,7 @@ func writeEncryptionToken(token []byte, cfg config.FolderConfiguration) error {
|
||||
})
|
||||
}
|
||||
|
||||
func newFolderConfiguration(w config.Wrapper, id, label string, fsType fs.FilesystemType, path string) config.FolderConfiguration {
|
||||
func newFolderConfiguration(w config.Wrapper, id, label string, fsType config.FilesystemType, path string) config.FolderConfiguration {
|
||||
fcfg := w.DefaultFolder()
|
||||
fcfg.ID = id
|
||||
fcfg.Label = label
|
||||
|
||||
+42
-42
@@ -391,7 +391,7 @@ func TestClusterConfig(t *testing.T) {
|
||||
}
|
||||
cfg.Folders = []config.FolderConfiguration{
|
||||
{
|
||||
FilesystemType: fs.FilesystemTypeFake,
|
||||
FilesystemType: config.FilesystemTypeFake,
|
||||
ID: "folder1",
|
||||
Path: "testdata1",
|
||||
Devices: []config.FolderDeviceConfiguration{
|
||||
@@ -400,7 +400,7 @@ func TestClusterConfig(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
FilesystemType: fs.FilesystemTypeFake,
|
||||
FilesystemType: config.FilesystemTypeFake,
|
||||
ID: "folder2",
|
||||
Path: "testdata2",
|
||||
Paused: true, // should still be included
|
||||
@@ -410,7 +410,7 @@ func TestClusterConfig(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
FilesystemType: fs.FilesystemTypeFake,
|
||||
FilesystemType: config.FilesystemTypeFake,
|
||||
ID: "folder3",
|
||||
Path: "testdata3",
|
||||
Devices: []config.FolderDeviceConfiguration{
|
||||
@@ -499,7 +499,7 @@ func TestIntroducer(t *testing.T) {
|
||||
},
|
||||
Folders: []config.FolderConfiguration{
|
||||
{
|
||||
FilesystemType: fs.FilesystemTypeFake,
|
||||
FilesystemType: config.FilesystemTypeFake,
|
||||
ID: "folder1",
|
||||
Path: "testdata",
|
||||
Devices: []config.FolderDeviceConfiguration{
|
||||
@@ -507,7 +507,7 @@ func TestIntroducer(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
FilesystemType: fs.FilesystemTypeFake,
|
||||
FilesystemType: config.FilesystemTypeFake,
|
||||
ID: "folder2",
|
||||
Path: "testdata",
|
||||
Devices: []config.FolderDeviceConfiguration{
|
||||
@@ -560,7 +560,7 @@ func TestIntroducer(t *testing.T) {
|
||||
},
|
||||
Folders: []config.FolderConfiguration{
|
||||
{
|
||||
FilesystemType: fs.FilesystemTypeFake,
|
||||
FilesystemType: config.FilesystemTypeFake,
|
||||
ID: "folder1",
|
||||
Path: "testdata",
|
||||
Devices: []config.FolderDeviceConfiguration{
|
||||
@@ -569,7 +569,7 @@ func TestIntroducer(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
FilesystemType: fs.FilesystemTypeFake,
|
||||
FilesystemType: config.FilesystemTypeFake,
|
||||
ID: "folder2",
|
||||
Path: "testdata",
|
||||
Devices: []config.FolderDeviceConfiguration{
|
||||
@@ -615,7 +615,7 @@ func TestIntroducer(t *testing.T) {
|
||||
},
|
||||
Folders: []config.FolderConfiguration{
|
||||
{
|
||||
FilesystemType: fs.FilesystemTypeFake,
|
||||
FilesystemType: config.FilesystemTypeFake,
|
||||
ID: "folder1",
|
||||
Path: "testdata",
|
||||
Devices: []config.FolderDeviceConfiguration{
|
||||
@@ -624,7 +624,7 @@ func TestIntroducer(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
FilesystemType: fs.FilesystemTypeFake,
|
||||
FilesystemType: config.FilesystemTypeFake,
|
||||
ID: "folder2",
|
||||
Path: "testdata",
|
||||
Devices: []config.FolderDeviceConfiguration{
|
||||
@@ -667,7 +667,7 @@ func TestIntroducer(t *testing.T) {
|
||||
},
|
||||
Folders: []config.FolderConfiguration{
|
||||
{
|
||||
FilesystemType: fs.FilesystemTypeFake,
|
||||
FilesystemType: config.FilesystemTypeFake,
|
||||
ID: "folder1",
|
||||
Path: "testdata",
|
||||
Devices: []config.FolderDeviceConfiguration{
|
||||
@@ -676,7 +676,7 @@ func TestIntroducer(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
FilesystemType: fs.FilesystemTypeFake,
|
||||
FilesystemType: config.FilesystemTypeFake,
|
||||
ID: "folder2",
|
||||
Path: "testdata",
|
||||
Devices: []config.FolderDeviceConfiguration{
|
||||
@@ -719,7 +719,7 @@ func TestIntroducer(t *testing.T) {
|
||||
},
|
||||
Folders: []config.FolderConfiguration{
|
||||
{
|
||||
FilesystemType: fs.FilesystemTypeFake,
|
||||
FilesystemType: config.FilesystemTypeFake,
|
||||
ID: "folder1",
|
||||
Path: "testdata",
|
||||
Devices: []config.FolderDeviceConfiguration{
|
||||
@@ -728,7 +728,7 @@ func TestIntroducer(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
FilesystemType: fs.FilesystemTypeFake,
|
||||
FilesystemType: config.FilesystemTypeFake,
|
||||
ID: "folder2",
|
||||
Path: "testdata",
|
||||
Devices: []config.FolderDeviceConfiguration{
|
||||
@@ -775,7 +775,7 @@ func TestIntroducer(t *testing.T) {
|
||||
},
|
||||
Folders: []config.FolderConfiguration{
|
||||
{
|
||||
FilesystemType: fs.FilesystemTypeFake,
|
||||
FilesystemType: config.FilesystemTypeFake,
|
||||
ID: "folder1",
|
||||
Path: "testdata",
|
||||
Devices: []config.FolderDeviceConfiguration{
|
||||
@@ -784,7 +784,7 @@ func TestIntroducer(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
FilesystemType: fs.FilesystemTypeFake,
|
||||
FilesystemType: config.FilesystemTypeFake,
|
||||
ID: "folder2",
|
||||
Path: "testdata",
|
||||
Devices: []config.FolderDeviceConfiguration{
|
||||
@@ -826,7 +826,7 @@ func TestIntroducer(t *testing.T) {
|
||||
},
|
||||
Folders: []config.FolderConfiguration{
|
||||
{
|
||||
FilesystemType: fs.FilesystemTypeFake,
|
||||
FilesystemType: config.FilesystemTypeFake,
|
||||
ID: "folder1",
|
||||
Path: "testdata",
|
||||
Devices: []config.FolderDeviceConfiguration{
|
||||
@@ -835,7 +835,7 @@ func TestIntroducer(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
FilesystemType: fs.FilesystemTypeFake,
|
||||
FilesystemType: config.FilesystemTypeFake,
|
||||
ID: "folder2",
|
||||
Path: "testdata",
|
||||
Devices: []config.FolderDeviceConfiguration{
|
||||
@@ -873,7 +873,7 @@ func TestIssue4897(t *testing.T) {
|
||||
},
|
||||
Folders: []config.FolderConfiguration{
|
||||
{
|
||||
FilesystemType: fs.FilesystemTypeFake,
|
||||
FilesystemType: config.FilesystemTypeFake,
|
||||
ID: "folder1",
|
||||
Path: "testdata",
|
||||
Devices: []config.FolderDeviceConfiguration{
|
||||
@@ -1030,7 +1030,7 @@ func TestAutoAcceptNewFolderPremutationsNoPanic(t *testing.T) {
|
||||
for _, dev2folder := range premutations {
|
||||
cfg := defaultAutoAcceptCfg.Copy()
|
||||
if localFolder.Label != "" {
|
||||
fcfg := newFolderConfiguration(defaultCfgWrapper, localFolder.ID, localFolder.Label, fs.FilesystemTypeFake, localFolder.ID)
|
||||
fcfg := newFolderConfiguration(defaultCfgWrapper, localFolder.ID, localFolder.Label, config.FilesystemTypeFake, localFolder.ID)
|
||||
fcfg.Paused = localFolderPaused
|
||||
cfg.Folders = append(cfg.Folders, fcfg)
|
||||
}
|
||||
@@ -1075,7 +1075,7 @@ func TestAutoAcceptExistingFolder(t *testing.T) {
|
||||
tcfg := defaultAutoAcceptCfg.Copy()
|
||||
tcfg.Folders = []config.FolderConfiguration{
|
||||
{
|
||||
FilesystemType: fs.FilesystemTypeFake,
|
||||
FilesystemType: config.FilesystemTypeFake,
|
||||
ID: id,
|
||||
Path: idOther, // To check that path does not get changed.
|
||||
},
|
||||
@@ -1101,7 +1101,7 @@ func TestAutoAcceptNewAndExistingFolder(t *testing.T) {
|
||||
tcfg := defaultAutoAcceptCfg.Copy()
|
||||
tcfg.Folders = []config.FolderConfiguration{
|
||||
{
|
||||
FilesystemType: fs.FilesystemTypeFake,
|
||||
FilesystemType: config.FilesystemTypeFake,
|
||||
ID: id1,
|
||||
Path: id1, // from previous test case, to verify that path doesn't get changed.
|
||||
},
|
||||
@@ -1127,7 +1127,7 @@ func TestAutoAcceptAlreadyShared(t *testing.T) {
|
||||
tcfg := defaultAutoAcceptCfg.Copy()
|
||||
tcfg.Folders = []config.FolderConfiguration{
|
||||
{
|
||||
FilesystemType: fs.FilesystemTypeFake,
|
||||
FilesystemType: config.FilesystemTypeFake,
|
||||
ID: id,
|
||||
Path: id,
|
||||
Devices: []config.FolderDeviceConfiguration{
|
||||
@@ -1226,7 +1226,7 @@ func TestAutoAcceptPausedWhenFolderConfigChanged(t *testing.T) {
|
||||
idOther := srand.String(8) // To check that path does not get changed.
|
||||
|
||||
tcfg := defaultAutoAcceptCfg.Copy()
|
||||
fcfg := newFolderConfiguration(defaultCfgWrapper, id, "", fs.FilesystemTypeFake, idOther)
|
||||
fcfg := newFolderConfiguration(defaultCfgWrapper, id, "", config.FilesystemTypeFake, idOther)
|
||||
fcfg.Paused = true
|
||||
// The order of devices here is wrong (cfg.clean() sorts them), which will cause the folder to restart.
|
||||
// Because of the restart, folder gets removed from m.deviceFolder, which means that generateClusterConfig will not panic.
|
||||
@@ -1272,7 +1272,7 @@ func TestAutoAcceptPausedWhenFolderConfigNotChanged(t *testing.T) {
|
||||
idOther := srand.String(8) // To check that path does not get changed.
|
||||
|
||||
tcfg := defaultAutoAcceptCfg.Copy()
|
||||
fcfg := newFolderConfiguration(defaultCfgWrapper, id, "", fs.FilesystemTypeFake, idOther)
|
||||
fcfg := newFolderConfiguration(defaultCfgWrapper, id, "", config.FilesystemTypeFake, idOther)
|
||||
fcfg.Paused = true
|
||||
// The new folder is exactly the same as the one constructed by handleAutoAccept, which means
|
||||
// the folder will not be restarted (even if it's paused), yet handleAutoAccept used to add the folder
|
||||
@@ -1521,7 +1521,7 @@ func TestIgnores(t *testing.T) {
|
||||
// Invalid path, treated like no patterns at all.
|
||||
fcfg := config.FolderConfiguration{
|
||||
ID: "fresh", Path: "XXX",
|
||||
FilesystemType: fs.FilesystemTypeFake,
|
||||
FilesystemType: config.FilesystemTypeFake,
|
||||
}
|
||||
ignores := ignore.New(fcfg.Filesystem(nil), ignore.WithCache(m.cfg.Options().CacheIgnoredFiles))
|
||||
m.mut.Lock()
|
||||
@@ -1609,7 +1609,7 @@ func waitForState(t *testing.T, sub events.Subscription, folder, expected string
|
||||
|
||||
func TestROScanRecovery(t *testing.T) {
|
||||
fcfg := config.FolderConfiguration{
|
||||
FilesystemType: fs.FilesystemTypeFake,
|
||||
FilesystemType: config.FilesystemTypeFake,
|
||||
ID: "default",
|
||||
Path: srand.String(32),
|
||||
Type: config.FolderTypeSendOnly,
|
||||
@@ -1656,7 +1656,7 @@ func TestROScanRecovery(t *testing.T) {
|
||||
|
||||
func TestRWScanRecovery(t *testing.T) {
|
||||
fcfg := config.FolderConfiguration{
|
||||
FilesystemType: fs.FilesystemTypeFake,
|
||||
FilesystemType: config.FilesystemTypeFake,
|
||||
ID: "default",
|
||||
Path: srand.String(32),
|
||||
Type: config.FolderTypeSendReceive,
|
||||
@@ -2522,7 +2522,7 @@ func TestVersionRestore(t *testing.T) {
|
||||
// We verify that the content matches at the expected filenames
|
||||
// after the restore operation.
|
||||
|
||||
fcfg := newFolderConfiguration(defaultCfgWrapper, "default", "default", fs.FilesystemTypeFake, srand.String(32))
|
||||
fcfg := newFolderConfiguration(defaultCfgWrapper, "default", "default", config.FilesystemTypeFake, srand.String(32))
|
||||
fcfg.Versioning.Type = "simple"
|
||||
fcfg.FSWatcherEnabled = false
|
||||
filesystem := fcfg.Filesystem(nil)
|
||||
@@ -2744,7 +2744,7 @@ func TestIssue4094(t *testing.T) {
|
||||
folderPath := "nonexistent"
|
||||
cfg := defaultCfgWrapper.RawCopy()
|
||||
fcfg := config.FolderConfiguration{
|
||||
FilesystemType: fs.FilesystemTypeFake,
|
||||
FilesystemType: config.FilesystemTypeFake,
|
||||
ID: "folder1",
|
||||
Path: folderPath,
|
||||
Paused: true,
|
||||
@@ -2861,7 +2861,7 @@ func TestFolderRestartZombies(t *testing.T) {
|
||||
waiter, err := wrapper.Modify(func(cfg *config.Configuration) {
|
||||
cfg.Options.RawMaxFolderConcurrency = -1
|
||||
_, i, _ := cfg.Folder("default")
|
||||
cfg.Folders[i].FilesystemType = fs.FilesystemTypeFake
|
||||
cfg.Folders[i].FilesystemType = config.FilesystemTypeFake
|
||||
})
|
||||
must(t, err)
|
||||
waiter.Wait()
|
||||
@@ -3204,7 +3204,7 @@ func TestRenameSequenceOrder(t *testing.T) {
|
||||
|
||||
count := 0
|
||||
snap := dbSnapshot(t, m, "default")
|
||||
snap.WithHave(protocol.LocalDeviceID, func(i protocol.FileIntf) bool {
|
||||
snap.WithHave(protocol.LocalDeviceID, func(i protocol.FileInfo) bool {
|
||||
count++
|
||||
return true
|
||||
})
|
||||
@@ -3236,7 +3236,7 @@ func TestRenameSequenceOrder(t *testing.T) {
|
||||
var firstExpectedSequence int64
|
||||
var secondExpectedSequence int64
|
||||
failed := false
|
||||
snap.WithHaveSequence(0, func(i protocol.FileIntf) bool {
|
||||
snap.WithHaveSequence(0, func(i protocol.FileInfo) bool {
|
||||
t.Log(i)
|
||||
if i.FileName() == "17" {
|
||||
firstExpectedSequence = i.SequenceNo() + 1
|
||||
@@ -3270,7 +3270,7 @@ func TestRenameSameFile(t *testing.T) {
|
||||
|
||||
count := 0
|
||||
snap := dbSnapshot(t, m, "default")
|
||||
snap.WithHave(protocol.LocalDeviceID, func(i protocol.FileIntf) bool {
|
||||
snap.WithHave(protocol.LocalDeviceID, func(i protocol.FileInfo) bool {
|
||||
count++
|
||||
return true
|
||||
})
|
||||
@@ -3293,7 +3293,7 @@ func TestRenameSameFile(t *testing.T) {
|
||||
|
||||
prevSeq := int64(0)
|
||||
seen := false
|
||||
snap.WithHaveSequence(0, func(i protocol.FileIntf) bool {
|
||||
snap.WithHaveSequence(0, func(i protocol.FileInfo) bool {
|
||||
if i.SequenceNo() <= prevSeq {
|
||||
t.Fatalf("non-increasing sequences: %d <= %d", i.SequenceNo(), prevSeq)
|
||||
}
|
||||
@@ -3333,7 +3333,7 @@ func TestRenameEmptyFile(t *testing.T) {
|
||||
}
|
||||
|
||||
count := 0
|
||||
snap.WithBlocksHash(empty.BlocksHash, func(_ protocol.FileIntf) bool {
|
||||
snap.WithBlocksHash(empty.BlocksHash, func(_ protocol.FileInfo) bool {
|
||||
count++
|
||||
return true
|
||||
})
|
||||
@@ -3343,7 +3343,7 @@ func TestRenameEmptyFile(t *testing.T) {
|
||||
}
|
||||
|
||||
count = 0
|
||||
snap.WithBlocksHash(file.BlocksHash, func(_ protocol.FileIntf) bool {
|
||||
snap.WithBlocksHash(file.BlocksHash, func(_ protocol.FileInfo) bool {
|
||||
count++
|
||||
return true
|
||||
})
|
||||
@@ -3362,7 +3362,7 @@ func TestRenameEmptyFile(t *testing.T) {
|
||||
defer snap.Release()
|
||||
|
||||
count = 0
|
||||
snap.WithBlocksHash(empty.BlocksHash, func(_ protocol.FileIntf) bool {
|
||||
snap.WithBlocksHash(empty.BlocksHash, func(_ protocol.FileInfo) bool {
|
||||
count++
|
||||
return true
|
||||
})
|
||||
@@ -3372,7 +3372,7 @@ func TestRenameEmptyFile(t *testing.T) {
|
||||
}
|
||||
|
||||
count = 0
|
||||
snap.WithBlocksHash(file.BlocksHash, func(i protocol.FileIntf) bool {
|
||||
snap.WithBlocksHash(file.BlocksHash, func(i protocol.FileInfo) bool {
|
||||
count++
|
||||
if i.FileName() != "new-file" {
|
||||
t.Fatalf("unexpected file name %s, expected new-file", i.FileName())
|
||||
@@ -3408,7 +3408,7 @@ func TestBlockListMap(t *testing.T) {
|
||||
}
|
||||
var paths []string
|
||||
|
||||
snap.WithBlocksHash(fi.BlocksHash, func(fi protocol.FileIntf) bool {
|
||||
snap.WithBlocksHash(fi.BlocksHash, func(fi protocol.FileInfo) bool {
|
||||
paths = append(paths, fi.FileName())
|
||||
return true
|
||||
})
|
||||
@@ -3441,7 +3441,7 @@ func TestBlockListMap(t *testing.T) {
|
||||
defer snap.Release()
|
||||
|
||||
paths = paths[:0]
|
||||
snap.WithBlocksHash(fi.BlocksHash, func(fi protocol.FileIntf) bool {
|
||||
snap.WithBlocksHash(fi.BlocksHash, func(fi protocol.FileInfo) bool {
|
||||
paths = append(paths, fi.FileName())
|
||||
return true
|
||||
})
|
||||
@@ -3468,7 +3468,7 @@ func TestScanRenameCaseOnly(t *testing.T) {
|
||||
snap := dbSnapshot(t, m, fcfg.ID)
|
||||
defer snap.Release()
|
||||
found := false
|
||||
snap.WithHave(protocol.LocalDeviceID, func(i protocol.FileIntf) bool {
|
||||
snap.WithHave(protocol.LocalDeviceID, func(i protocol.FileInfo) bool {
|
||||
if found {
|
||||
t.Fatal("got more than one file")
|
||||
}
|
||||
@@ -3487,7 +3487,7 @@ func TestScanRenameCaseOnly(t *testing.T) {
|
||||
snap = dbSnapshot(t, m, fcfg.ID)
|
||||
defer snap.Release()
|
||||
found = false
|
||||
snap.WithHave(protocol.LocalDeviceID, func(i protocol.FileIntf) bool {
|
||||
snap.WithHave(protocol.LocalDeviceID, func(i protocol.FileInfo) bool {
|
||||
if i.FileName() == name {
|
||||
if i.IsDeleted() {
|
||||
return true
|
||||
|
||||
@@ -12,6 +12,9 @@ import (
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
"github.com/syncthing/syncthing/internal/protoutil"
|
||||
"github.com/syncthing/syncthing/lib/fs"
|
||||
"github.com/syncthing/syncthing/lib/osutil"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
@@ -386,7 +389,7 @@ func writeEncryptionTrailer(file protocol.FileInfo, writer io.WriterAt) (int64,
|
||||
|
||||
trailerSize := encryptionTrailerSize(wireFile)
|
||||
bs := make([]byte, trailerSize)
|
||||
n, err := wireFile.MarshalTo(bs)
|
||||
n, err := protoutil.MarshalTo(bs, wireFile.ToWire(false))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -401,7 +404,7 @@ func writeEncryptionTrailer(file protocol.FileInfo, writer io.WriterAt) (int64,
|
||||
}
|
||||
|
||||
func encryptionTrailerSize(file protocol.FileInfo) int64 {
|
||||
return int64(file.ProtoSize()) + 4
|
||||
return int64(proto.Size(file.ToWire(false))) + 4 // XXX: Inefficient
|
||||
}
|
||||
|
||||
// Progress returns the momentarily progress for the puller
|
||||
|
||||
@@ -75,7 +75,7 @@ func init() {
|
||||
},
|
||||
Defaults: config.Defaults{
|
||||
Folder: config.FolderConfiguration{
|
||||
FilesystemType: fs.FilesystemTypeFake,
|
||||
FilesystemType: config.FilesystemTypeFake,
|
||||
Path: rand.String(32),
|
||||
},
|
||||
},
|
||||
@@ -102,7 +102,7 @@ func newDefaultCfgWrapper() (config.Wrapper, config.FolderConfiguration, context
|
||||
}
|
||||
|
||||
func newFolderConfig() config.FolderConfiguration {
|
||||
cfg := newFolderConfiguration(defaultCfgWrapper, "default", "default", fs.FilesystemTypeFake, rand.String(32)+"?content=true")
|
||||
cfg := newFolderConfiguration(defaultCfgWrapper, "default", "default", config.FilesystemTypeFake, rand.String(32)+"?content=true")
|
||||
cfg.FSWatcherEnabled = false
|
||||
cfg.Devices = append(cfg.Devices, config.FolderDeviceConfiguration{DeviceID: device1})
|
||||
return cfg
|
||||
|
||||
@@ -73,7 +73,7 @@ func RenameOrCopy(method fs.CopyRangeMethod, src, dst fs.Filesystem, from, to st
|
||||
// Copy copies the file content from source to destination.
|
||||
// Tries hard to succeed on various systems by temporarily tweaking directory
|
||||
// permissions and removing the destination file when necessary.
|
||||
func Copy(method fs.CopyRangeMethod, src, dst fs.Filesystem, from, to string) (err error) {
|
||||
func Copy(method fs.CopyRangeMethod, src, dst fs.Filesystem, from, to string) error {
|
||||
return withPreparedTarget(dst, from, to, func() error {
|
||||
return copyFileContents(method, src, dst, from, to)
|
||||
})
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
Copyright (C) 2014-2015 The Protocol Authors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
- The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -1,4 +1,8 @@
|
||||
// Copyright (C) 2016 The Protocol Authors.
|
||||
// Copyright (C) 2016 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 protocol
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,147 @@
|
||||
// Copyright (C) 2014 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 protocol
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/syncthing/syncthing/internal/gen/bep"
|
||||
)
|
||||
|
||||
type Compression = bep.Compression
|
||||
|
||||
const (
|
||||
CompressionMetadata = bep.Compression_COMPRESSION_METADATA
|
||||
CompressionNever = bep.Compression_COMPRESSION_NEVER
|
||||
CompressionAlways = bep.Compression_COMPRESSION_ALWAYS
|
||||
)
|
||||
|
||||
type ClusterConfig struct {
|
||||
Folders []Folder
|
||||
Secondary bool
|
||||
}
|
||||
|
||||
func (c *ClusterConfig) toWire() *bep.ClusterConfig {
|
||||
folders := make([]*bep.Folder, len(c.Folders))
|
||||
for i, f := range c.Folders {
|
||||
folders[i] = f.toWire()
|
||||
}
|
||||
return &bep.ClusterConfig{
|
||||
Folders: folders,
|
||||
Secondary: c.Secondary,
|
||||
}
|
||||
}
|
||||
|
||||
func clusterConfigFromWire(w *bep.ClusterConfig) *ClusterConfig {
|
||||
if w == nil {
|
||||
return nil
|
||||
}
|
||||
c := &ClusterConfig{
|
||||
Secondary: w.Secondary,
|
||||
}
|
||||
c.Folders = make([]Folder, len(w.Folders))
|
||||
for i, f := range w.Folders {
|
||||
c.Folders[i] = folderFromWire(f)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
type Folder struct {
|
||||
ID string
|
||||
Label string
|
||||
ReadOnly bool
|
||||
IgnorePermissions bool
|
||||
IgnoreDelete bool
|
||||
DisableTempIndexes bool
|
||||
Paused bool
|
||||
Devices []Device
|
||||
}
|
||||
|
||||
func (f *Folder) toWire() *bep.Folder {
|
||||
devices := make([]*bep.Device, len(f.Devices))
|
||||
for i, d := range f.Devices {
|
||||
devices[i] = d.toWire()
|
||||
}
|
||||
return &bep.Folder{
|
||||
Id: f.ID,
|
||||
Label: f.Label,
|
||||
ReadOnly: f.ReadOnly,
|
||||
IgnorePermissions: f.IgnorePermissions,
|
||||
IgnoreDelete: f.IgnoreDelete,
|
||||
DisableTempIndexes: f.DisableTempIndexes,
|
||||
Paused: f.Paused,
|
||||
Devices: devices,
|
||||
}
|
||||
}
|
||||
|
||||
func folderFromWire(w *bep.Folder) Folder {
|
||||
devices := make([]Device, len(w.Devices))
|
||||
for i, d := range w.Devices {
|
||||
devices[i] = deviceFromWire(d)
|
||||
}
|
||||
return Folder{
|
||||
ID: w.Id,
|
||||
Label: w.Label,
|
||||
ReadOnly: w.ReadOnly,
|
||||
IgnorePermissions: w.IgnorePermissions,
|
||||
IgnoreDelete: w.IgnoreDelete,
|
||||
DisableTempIndexes: w.DisableTempIndexes,
|
||||
Paused: w.Paused,
|
||||
Devices: devices,
|
||||
}
|
||||
}
|
||||
|
||||
func (f Folder) Description() string {
|
||||
// used by logging stuff
|
||||
if f.Label == "" {
|
||||
return f.ID
|
||||
}
|
||||
return fmt.Sprintf("%q (%s)", f.Label, f.ID)
|
||||
}
|
||||
|
||||
type Device struct {
|
||||
ID DeviceID
|
||||
Name string
|
||||
Addresses []string
|
||||
Compression Compression
|
||||
CertName string
|
||||
MaxSequence int64
|
||||
Introducer bool
|
||||
IndexID IndexID
|
||||
SkipIntroductionRemovals bool
|
||||
EncryptionPasswordToken []byte
|
||||
}
|
||||
|
||||
func (d *Device) toWire() *bep.Device {
|
||||
return &bep.Device{
|
||||
Id: d.ID[:],
|
||||
Name: d.Name,
|
||||
Addresses: d.Addresses,
|
||||
Compression: d.Compression,
|
||||
CertName: d.CertName,
|
||||
MaxSequence: d.MaxSequence,
|
||||
Introducer: d.Introducer,
|
||||
IndexId: uint64(d.IndexID),
|
||||
SkipIntroductionRemovals: d.SkipIntroductionRemovals,
|
||||
EncryptionPasswordToken: d.EncryptionPasswordToken,
|
||||
}
|
||||
}
|
||||
|
||||
func deviceFromWire(w *bep.Device) Device {
|
||||
return Device{
|
||||
ID: DeviceID(w.Id),
|
||||
Name: w.Name,
|
||||
Addresses: w.Addresses,
|
||||
Compression: w.Compression,
|
||||
CertName: w.CertName,
|
||||
MaxSequence: w.MaxSequence,
|
||||
Introducer: w.Introducer,
|
||||
IndexID: IndexID(w.IndexId),
|
||||
SkipIntroductionRemovals: w.SkipIntroductionRemovals,
|
||||
EncryptionPasswordToken: w.EncryptionPasswordToken,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
// Copyright (C) 2016 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 protocol
|
||||
|
||||
import "github.com/syncthing/syncthing/internal/gen/bep"
|
||||
|
||||
type FileDownloadProgressUpdateType = bep.FileDownloadProgressUpdateType
|
||||
|
||||
const (
|
||||
FileDownloadProgressUpdateTypeAppend = bep.FileDownloadProgressUpdateType_FILE_DOWNLOAD_PROGRESS_UPDATE_TYPE_APPEND
|
||||
FileDownloadProgressUpdateTypeForget = bep.FileDownloadProgressUpdateType_FILE_DOWNLOAD_PROGRESS_UPDATE_TYPE_FORGET
|
||||
)
|
||||
|
||||
type DownloadProgress struct {
|
||||
Folder string
|
||||
Updates []FileDownloadProgressUpdate
|
||||
}
|
||||
|
||||
func (d *DownloadProgress) toWire() *bep.DownloadProgress {
|
||||
updates := make([]*bep.FileDownloadProgressUpdate, len(d.Updates))
|
||||
for i, u := range d.Updates {
|
||||
updates[i] = u.toWire()
|
||||
}
|
||||
return &bep.DownloadProgress{
|
||||
Folder: d.Folder,
|
||||
Updates: updates,
|
||||
}
|
||||
}
|
||||
|
||||
func downloadProgressFromWire(w *bep.DownloadProgress) *DownloadProgress {
|
||||
dp := &DownloadProgress{
|
||||
Folder: w.Folder,
|
||||
Updates: make([]FileDownloadProgressUpdate, len(w.Updates)),
|
||||
}
|
||||
for i, u := range w.Updates {
|
||||
dp.Updates[i] = fileDownloadProgressUpdateFromWire(u)
|
||||
}
|
||||
return dp
|
||||
}
|
||||
|
||||
type FileDownloadProgressUpdate struct {
|
||||
UpdateType FileDownloadProgressUpdateType
|
||||
Name string
|
||||
Version Vector
|
||||
BlockIndexes []int
|
||||
BlockSize int
|
||||
}
|
||||
|
||||
func (f *FileDownloadProgressUpdate) toWire() *bep.FileDownloadProgressUpdate {
|
||||
bidxs := make([]int32, len(f.BlockIndexes))
|
||||
for i, b := range f.BlockIndexes {
|
||||
bidxs[i] = int32(b)
|
||||
}
|
||||
return &bep.FileDownloadProgressUpdate{
|
||||
UpdateType: f.UpdateType,
|
||||
Name: f.Name,
|
||||
Version: f.Version.ToWire(),
|
||||
BlockIndexes: bidxs,
|
||||
BlockSize: int32(f.BlockSize),
|
||||
}
|
||||
}
|
||||
|
||||
func fileDownloadProgressUpdateFromWire(w *bep.FileDownloadProgressUpdate) FileDownloadProgressUpdate {
|
||||
bidxs := make([]int, len(w.BlockIndexes))
|
||||
for i, b := range w.BlockIndexes {
|
||||
bidxs[i] = int(b)
|
||||
}
|
||||
return FileDownloadProgressUpdate{
|
||||
UpdateType: w.UpdateType,
|
||||
Name: w.Name,
|
||||
Version: VectorFromWire(w.Version),
|
||||
BlockIndexes: bidxs,
|
||||
BlockSize: int(w.BlockSize),
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,8 @@
|
||||
// Copyright (C) 2014 The Protocol Authors.
|
||||
// Copyright (C) 2014 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 protocol
|
||||
|
||||
@@ -6,51 +10,240 @@ import (
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/syncthing/syncthing/internal/gen/bep"
|
||||
"github.com/syncthing/syncthing/lib/build"
|
||||
"github.com/syncthing/syncthing/lib/rand"
|
||||
)
|
||||
|
||||
// FileInfo.LocalFlags flags
|
||||
const (
|
||||
SyntheticDirectorySize = 128
|
||||
HelloMessageMagic uint32 = 0x2EA7D90B
|
||||
Version13HelloMagic uint32 = 0x9F79BC40 // old
|
||||
FlagLocalUnsupported = 1 << 0 // The kind is unsupported, e.g. symlinks on Windows
|
||||
FlagLocalIgnored = 1 << 1 // Matches local ignore patterns
|
||||
FlagLocalMustRescan = 1 << 2 // Doesn't match content on disk, must be rechecked fully
|
||||
FlagLocalReceiveOnly = 1 << 3 // Change detected on receive only folder
|
||||
|
||||
// Flags that should result in the Invalid bit on outgoing updates
|
||||
LocalInvalidFlags = FlagLocalUnsupported | FlagLocalIgnored | FlagLocalMustRescan | FlagLocalReceiveOnly
|
||||
|
||||
// Flags that should result in a file being in conflict with its
|
||||
// successor, due to us not having an up to date picture of its state on
|
||||
// disk.
|
||||
LocalConflictFlags = FlagLocalUnsupported | FlagLocalIgnored | FlagLocalReceiveOnly
|
||||
|
||||
LocalAllFlags = FlagLocalUnsupported | FlagLocalIgnored | FlagLocalMustRescan | FlagLocalReceiveOnly
|
||||
)
|
||||
|
||||
// FileIntf is the set of methods implemented by both FileInfo and
|
||||
// db.FileInfoTruncated.
|
||||
type FileIntf interface {
|
||||
FileSize() int64
|
||||
FileName() string
|
||||
FileLocalFlags() uint32
|
||||
IsDeleted() bool
|
||||
IsInvalid() bool
|
||||
IsIgnored() bool
|
||||
IsUnsupported() bool
|
||||
MustRescan() bool
|
||||
IsReceiveOnlyChanged() bool
|
||||
IsDirectory() bool
|
||||
IsSymlink() bool
|
||||
ShouldConflict() bool
|
||||
HasPermissionBits() bool
|
||||
SequenceNo() int64
|
||||
BlockSize() int
|
||||
FileVersion() Vector
|
||||
FileType() FileInfoType
|
||||
FilePermissions() uint32
|
||||
FileModifiedBy() ShortID
|
||||
ModTime() time.Time
|
||||
PlatformData() PlatformData
|
||||
InodeChangeTime() time.Time
|
||||
FileBlocksHash() []byte
|
||||
// BlockSizes is the list of valid block sizes, from min to max
|
||||
var BlockSizes []int
|
||||
|
||||
func init() {
|
||||
for blockSize := MinBlockSize; blockSize <= MaxBlockSize; blockSize *= 2 {
|
||||
BlockSizes = append(BlockSizes, blockSize)
|
||||
if _, ok := sha256OfEmptyBlock[blockSize]; !ok {
|
||||
panic("missing hard coded value for sha256 of empty block")
|
||||
}
|
||||
}
|
||||
BufferPool = newBufferPool() // must happen after BlockSizes is initialized
|
||||
}
|
||||
|
||||
func (Hello) Magic() uint32 {
|
||||
return HelloMessageMagic
|
||||
type FileInfoType = bep.FileInfoType
|
||||
|
||||
const (
|
||||
FileInfoTypeFile = bep.FileInfoType_FILE_INFO_TYPE_FILE
|
||||
FileInfoTypeDirectory = bep.FileInfoType_FILE_INFO_TYPE_DIRECTORY
|
||||
FileInfoTypeSymlinkFile = bep.FileInfoType_FILE_INFO_TYPE_SYMLINK_FILE
|
||||
FileInfoTypeSymlinkDirectory = bep.FileInfoType_FILE_INFO_TYPE_SYMLINK_DIRECTORY
|
||||
FileInfoTypeSymlink = bep.FileInfoType_FILE_INFO_TYPE_SYMLINK
|
||||
)
|
||||
|
||||
type FileInfo struct {
|
||||
Name string
|
||||
Size int64
|
||||
ModifiedS int64
|
||||
ModifiedBy ShortID
|
||||
Version Vector
|
||||
Sequence int64
|
||||
Blocks []BlockInfo
|
||||
SymlinkTarget string
|
||||
BlocksHash []byte
|
||||
Encrypted []byte
|
||||
Platform PlatformData
|
||||
|
||||
Type FileInfoType
|
||||
Permissions uint32
|
||||
ModifiedNs int32
|
||||
RawBlockSize int32
|
||||
|
||||
// The local_flags fields stores flags that are relevant to the local
|
||||
// host only. It is not part of the protocol, doesn't get sent or
|
||||
// received (we make sure to zero it), nonetheless we need it on our
|
||||
// struct and to be able to serialize it to/from the database.
|
||||
LocalFlags uint32
|
||||
|
||||
// The version_hash is an implementation detail and not part of the wire
|
||||
// format.
|
||||
VersionHash []byte
|
||||
|
||||
// The time when the inode was last changed (i.e., permissions, xattrs
|
||||
// etc changed). This is host-local, not sent over the wire.
|
||||
InodeChangeNs int64
|
||||
|
||||
// The size of the data appended to the encrypted file on disk. This is
|
||||
// host-local, not sent over the wire.
|
||||
EncryptionTrailerSize int
|
||||
|
||||
Deleted bool
|
||||
RawInvalid bool
|
||||
NoPermissions bool
|
||||
|
||||
truncated bool // was created from a truncated file info without blocks
|
||||
}
|
||||
|
||||
func (f *FileInfo) ToWire(withInternalFields bool) *bep.FileInfo {
|
||||
if f.truncated && !(f.IsDeleted() || f.IsInvalid() || f.IsIgnored()) {
|
||||
panic("bug: must not serialize truncated file info")
|
||||
}
|
||||
blocks := make([]*bep.BlockInfo, len(f.Blocks))
|
||||
for j, b := range f.Blocks {
|
||||
blocks[j] = b.ToWire()
|
||||
}
|
||||
w := &bep.FileInfo{
|
||||
Name: f.Name,
|
||||
Size: f.Size,
|
||||
ModifiedS: f.ModifiedS,
|
||||
ModifiedBy: uint64(f.ModifiedBy),
|
||||
Version: f.Version.ToWire(),
|
||||
Sequence: f.Sequence,
|
||||
Blocks: blocks,
|
||||
SymlinkTarget: f.SymlinkTarget,
|
||||
BlocksHash: f.BlocksHash,
|
||||
Encrypted: f.Encrypted,
|
||||
Type: f.Type,
|
||||
Permissions: f.Permissions,
|
||||
ModifiedNs: f.ModifiedNs,
|
||||
BlockSize: f.RawBlockSize,
|
||||
Platform: f.Platform.toWire(),
|
||||
Deleted: f.Deleted,
|
||||
Invalid: f.RawInvalid,
|
||||
NoPermissions: f.NoPermissions,
|
||||
}
|
||||
if withInternalFields {
|
||||
w.LocalFlags = f.LocalFlags
|
||||
w.VersionHash = f.VersionHash
|
||||
w.InodeChangeNs = f.InodeChangeNs
|
||||
w.EncryptionTrailerSize = int32(f.EncryptionTrailerSize)
|
||||
}
|
||||
return w
|
||||
}
|
||||
|
||||
// WinsConflict returns true if "f" is the one to choose when it is in
|
||||
// conflict with "other".
|
||||
func (f *FileInfo) WinsConflict(other FileInfo) bool {
|
||||
// If only one of the files is invalid, that one loses.
|
||||
if f.IsInvalid() != other.IsInvalid() {
|
||||
return !f.IsInvalid()
|
||||
}
|
||||
|
||||
// If a modification is in conflict with a delete, we pick the
|
||||
// modification.
|
||||
if !f.IsDeleted() && other.IsDeleted() {
|
||||
return true
|
||||
}
|
||||
if f.IsDeleted() && !other.IsDeleted() {
|
||||
return false
|
||||
}
|
||||
|
||||
// The one with the newer modification time wins.
|
||||
if f.ModTime().After(other.ModTime()) {
|
||||
return true
|
||||
}
|
||||
if f.ModTime().Before(other.ModTime()) {
|
||||
return false
|
||||
}
|
||||
|
||||
// The modification times were equal. Use the device ID in the version
|
||||
// vector as tie breaker.
|
||||
return f.FileVersion().Compare(other.FileVersion()) == ConcurrentGreater
|
||||
}
|
||||
|
||||
func FileInfoFromWire(w *bep.FileInfo) FileInfo {
|
||||
var blocks []BlockInfo
|
||||
if len(w.Blocks) > 0 {
|
||||
blocks = make([]BlockInfo, len(w.Blocks))
|
||||
for j, b := range w.Blocks {
|
||||
blocks[j] = BlockInfoFromWire(b)
|
||||
}
|
||||
}
|
||||
return fileInfoFromWireWithBlocks(w, blocks)
|
||||
}
|
||||
|
||||
type FileInfoWithoutBlocks interface {
|
||||
GetName() string
|
||||
GetSize() int64
|
||||
GetModifiedS() int64
|
||||
GetModifiedBy() uint64
|
||||
GetVersion() *bep.Vector
|
||||
GetSequence() int64
|
||||
// GetBlocks() []*bep.BlockInfo // not included
|
||||
GetSymlinkTarget() string
|
||||
GetBlocksHash() []byte
|
||||
GetEncrypted() []byte
|
||||
GetType() FileInfoType
|
||||
GetPermissions() uint32
|
||||
GetModifiedNs() int32
|
||||
GetBlockSize() int32
|
||||
GetPlatform() *bep.PlatformData
|
||||
GetLocalFlags() uint32
|
||||
GetVersionHash() []byte
|
||||
GetInodeChangeNs() int64
|
||||
GetEncryptionTrailerSize() int32
|
||||
GetDeleted() bool
|
||||
GetInvalid() bool
|
||||
GetNoPermissions() bool
|
||||
}
|
||||
|
||||
func fileInfoFromWireWithBlocks(w FileInfoWithoutBlocks, blocks []BlockInfo) FileInfo {
|
||||
return FileInfo{
|
||||
Name: w.GetName(),
|
||||
Size: w.GetSize(),
|
||||
ModifiedS: w.GetModifiedS(),
|
||||
ModifiedBy: ShortID(w.GetModifiedBy()),
|
||||
Version: VectorFromWire(w.GetVersion()),
|
||||
Sequence: w.GetSequence(),
|
||||
Blocks: blocks,
|
||||
SymlinkTarget: w.GetSymlinkTarget(),
|
||||
BlocksHash: w.GetBlocksHash(),
|
||||
Encrypted: w.GetEncrypted(),
|
||||
Type: w.GetType(),
|
||||
Permissions: w.GetPermissions(),
|
||||
ModifiedNs: w.GetModifiedNs(),
|
||||
RawBlockSize: w.GetBlockSize(),
|
||||
Platform: platformDataFromWire(w.GetPlatform()),
|
||||
Deleted: w.GetDeleted(),
|
||||
RawInvalid: w.GetInvalid(),
|
||||
NoPermissions: w.GetNoPermissions(),
|
||||
}
|
||||
}
|
||||
|
||||
func FileInfoFromDB(w *bep.FileInfo) FileInfo {
|
||||
f := FileInfoFromWire(w)
|
||||
f.LocalFlags = w.LocalFlags
|
||||
f.VersionHash = w.VersionHash
|
||||
f.InodeChangeNs = w.InodeChangeNs
|
||||
f.EncryptionTrailerSize = int(w.EncryptionTrailerSize)
|
||||
return f
|
||||
}
|
||||
|
||||
func FileInfoFromDBTruncated(w FileInfoWithoutBlocks) FileInfo {
|
||||
f := fileInfoFromWireWithBlocks(w, nil)
|
||||
f.LocalFlags = w.GetLocalFlags()
|
||||
f.VersionHash = w.GetVersionHash()
|
||||
f.InodeChangeNs = w.GetInodeChangeNs()
|
||||
f.EncryptionTrailerSize = int(w.GetEncryptionTrailerSize())
|
||||
f.truncated = true
|
||||
return f
|
||||
}
|
||||
|
||||
func (f FileInfo) String() string {
|
||||
@@ -128,7 +321,19 @@ func (f FileInfo) BlockSize() int {
|
||||
if f.RawBlockSize < MinBlockSize {
|
||||
return MinBlockSize
|
||||
}
|
||||
return f.RawBlockSize
|
||||
return int(f.RawBlockSize)
|
||||
}
|
||||
|
||||
// BlockSize returns the block size to use for the given file size
|
||||
func BlockSize(fileSize int64) int {
|
||||
var blockSize int
|
||||
for _, blockSize = range BlockSizes {
|
||||
if fileSize < DesiredPerFileBlocks*int64(blockSize) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return blockSize
|
||||
}
|
||||
|
||||
func (f FileInfo) FileName() string {
|
||||
@@ -175,36 +380,6 @@ func (f FileInfo) FileBlocksHash() []byte {
|
||||
return f.BlocksHash
|
||||
}
|
||||
|
||||
// WinsConflict returns true if "f" is the one to choose when it is in
|
||||
// conflict with "other".
|
||||
func WinsConflict(f, other FileIntf) bool {
|
||||
// If only one of the files is invalid, that one loses.
|
||||
if f.IsInvalid() != other.IsInvalid() {
|
||||
return !f.IsInvalid()
|
||||
}
|
||||
|
||||
// If a modification is in conflict with a delete, we pick the
|
||||
// modification.
|
||||
if !f.IsDeleted() && other.IsDeleted() {
|
||||
return true
|
||||
}
|
||||
if f.IsDeleted() && !other.IsDeleted() {
|
||||
return false
|
||||
}
|
||||
|
||||
// The one with the newer modification time wins.
|
||||
if f.ModTime().After(other.ModTime()) {
|
||||
return true
|
||||
}
|
||||
if f.ModTime().Before(other.ModTime()) {
|
||||
return false
|
||||
}
|
||||
|
||||
// The modification times were equal. Use the device ID in the version
|
||||
// vector as tie breaker.
|
||||
return f.FileVersion().Compare(other.FileVersion()) == ConcurrentGreater
|
||||
}
|
||||
|
||||
type FileInfoComparison struct {
|
||||
ModTimeWindow time.Duration
|
||||
IgnorePerms bool
|
||||
@@ -336,18 +511,121 @@ func (f FileInfo) BlocksEqual(other FileInfo) bool {
|
||||
return blocksEqual(f.Blocks, other.Blocks)
|
||||
}
|
||||
|
||||
func (f *FileInfo) SetMustRescan() {
|
||||
f.setLocalFlags(FlagLocalMustRescan)
|
||||
}
|
||||
|
||||
func (f *FileInfo) SetIgnored() {
|
||||
f.setLocalFlags(FlagLocalIgnored)
|
||||
}
|
||||
|
||||
func (f *FileInfo) SetUnsupported() {
|
||||
f.setLocalFlags(FlagLocalUnsupported)
|
||||
}
|
||||
|
||||
func (f *FileInfo) SetDeleted(by ShortID) {
|
||||
f.ModifiedBy = by
|
||||
f.Deleted = true
|
||||
f.Version = f.Version.Update(by)
|
||||
f.ModifiedS = time.Now().Unix()
|
||||
f.setNoContent()
|
||||
}
|
||||
|
||||
func (f *FileInfo) setLocalFlags(flags uint32) {
|
||||
f.RawInvalid = false
|
||||
f.LocalFlags = flags
|
||||
f.setNoContent()
|
||||
}
|
||||
|
||||
func (f *FileInfo) setNoContent() {
|
||||
f.Blocks = nil
|
||||
f.BlocksHash = nil
|
||||
f.Size = 0
|
||||
}
|
||||
|
||||
type BlockInfo struct {
|
||||
Hash []byte
|
||||
Offset int64
|
||||
Size int
|
||||
WeakHash uint32
|
||||
}
|
||||
|
||||
func (b BlockInfo) ToWire() *bep.BlockInfo {
|
||||
return &bep.BlockInfo{
|
||||
Hash: b.Hash,
|
||||
Offset: b.Offset,
|
||||
Size: int32(b.Size),
|
||||
WeakHash: b.WeakHash,
|
||||
}
|
||||
}
|
||||
|
||||
func BlockInfoFromWire(w *bep.BlockInfo) BlockInfo {
|
||||
return BlockInfo{
|
||||
Hash: w.Hash,
|
||||
Offset: w.Offset,
|
||||
Size: int(w.Size),
|
||||
WeakHash: w.WeakHash,
|
||||
}
|
||||
}
|
||||
|
||||
func (b BlockInfo) String() string {
|
||||
return fmt.Sprintf("Block{%d/%d/%d/%x}", b.Offset, b.Size, b.WeakHash, b.Hash)
|
||||
}
|
||||
|
||||
// For each block size, the hash of a block of all zeroes
|
||||
var sha256OfEmptyBlock = map[int][sha256.Size]byte{
|
||||
128 << KiB: {0xfa, 0x43, 0x23, 0x9b, 0xce, 0xe7, 0xb9, 0x7c, 0xa6, 0x2f, 0x0, 0x7c, 0xc6, 0x84, 0x87, 0x56, 0xa, 0x39, 0xe1, 0x9f, 0x74, 0xf3, 0xdd, 0xe7, 0x48, 0x6d, 0xb3, 0xf9, 0x8d, 0xf8, 0xe4, 0x71},
|
||||
256 << KiB: {0x8a, 0x39, 0xd2, 0xab, 0xd3, 0x99, 0x9a, 0xb7, 0x3c, 0x34, 0xdb, 0x24, 0x76, 0x84, 0x9c, 0xdd, 0xf3, 0x3, 0xce, 0x38, 0x9b, 0x35, 0x82, 0x68, 0x50, 0xf9, 0xa7, 0x0, 0x58, 0x9b, 0x4a, 0x90},
|
||||
512 << KiB: {0x7, 0x85, 0x4d, 0x2f, 0xef, 0x29, 0x7a, 0x6, 0xba, 0x81, 0x68, 0x5e, 0x66, 0xc, 0x33, 0x2d, 0xe3, 0x6d, 0x5d, 0x18, 0xd5, 0x46, 0x92, 0x7d, 0x30, 0xda, 0xad, 0x6d, 0x7f, 0xda, 0x15, 0x41},
|
||||
1 << MiB: {0x30, 0xe1, 0x49, 0x55, 0xeb, 0xf1, 0x35, 0x22, 0x66, 0xdc, 0x2f, 0xf8, 0x6, 0x7e, 0x68, 0x10, 0x46, 0x7, 0xe7, 0x50, 0xab, 0xb9, 0xd3, 0xb3, 0x65, 0x82, 0xb8, 0xaf, 0x90, 0x9f, 0xcb, 0x58},
|
||||
2 << MiB: {0x56, 0x47, 0xf0, 0x5e, 0xc1, 0x89, 0x58, 0x94, 0x7d, 0x32, 0x87, 0x4e, 0xeb, 0x78, 0x8f, 0xa3, 0x96, 0xa0, 0x5d, 0xb, 0xab, 0x7c, 0x1b, 0x71, 0xf1, 0x12, 0xce, 0xb7, 0xe9, 0xb3, 0x1e, 0xee},
|
||||
4 << MiB: {0xbb, 0x9f, 0x8d, 0xf6, 0x14, 0x74, 0xd2, 0x5e, 0x71, 0xfa, 0x0, 0x72, 0x23, 0x18, 0xcd, 0x38, 0x73, 0x96, 0xca, 0x17, 0x36, 0x60, 0x5e, 0x12, 0x48, 0x82, 0x1c, 0xc0, 0xde, 0x3d, 0x3a, 0xf8},
|
||||
8 << MiB: {0x2d, 0xae, 0xb1, 0xf3, 0x60, 0x95, 0xb4, 0x4b, 0x31, 0x84, 0x10, 0xb3, 0xf4, 0xe8, 0xb5, 0xd9, 0x89, 0xdc, 0xc7, 0xbb, 0x2, 0x3d, 0x14, 0x26, 0xc4, 0x92, 0xda, 0xb0, 0xa3, 0x5, 0x3e, 0x74},
|
||||
16 << MiB: {0x8, 0xa, 0xcf, 0x35, 0xa5, 0x7, 0xac, 0x98, 0x49, 0xcf, 0xcb, 0xa4, 0x7d, 0xc2, 0xad, 0x83, 0xe0, 0x1b, 0x75, 0x66, 0x3a, 0x51, 0x62, 0x79, 0xc8, 0xb9, 0xd2, 0x43, 0xb7, 0x19, 0x64, 0x3e},
|
||||
}
|
||||
|
||||
// IsEmpty returns true if the block is a full block of zeroes.
|
||||
func (b BlockInfo) IsEmpty() bool {
|
||||
if v, ok := sha256OfEmptyBlock[b.Size]; ok {
|
||||
return bytes.Equal(b.Hash, v[:])
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func BlocksHash(bs []BlockInfo) []byte {
|
||||
h := sha256.New()
|
||||
for _, b := range bs {
|
||||
_, _ = h.Write(b.Hash)
|
||||
_ = binary.Write(h, binary.BigEndian, b.WeakHash)
|
||||
}
|
||||
return h.Sum(nil)
|
||||
}
|
||||
|
||||
func VectorHash(v Vector) []byte {
|
||||
h := sha256.New()
|
||||
for _, c := range v.Counters {
|
||||
if err := binary.Write(h, binary.BigEndian, c.ID); err != nil {
|
||||
panic("impossible: failed to write c.ID to hash function: " + err.Error())
|
||||
}
|
||||
if err := binary.Write(h, binary.BigEndian, c.Value); err != nil {
|
||||
panic("impossible: failed to write c.Value to hash function: " + err.Error())
|
||||
}
|
||||
}
|
||||
return h.Sum(nil)
|
||||
}
|
||||
|
||||
// Xattrs is a convenience method to return the extended attributes of the
|
||||
// file for the current platform.
|
||||
func (f *PlatformData) Xattrs() []Xattr {
|
||||
func (p *PlatformData) Xattrs() []Xattr {
|
||||
switch {
|
||||
case build.IsLinux && f.Linux != nil:
|
||||
return f.Linux.Xattrs
|
||||
case build.IsDarwin && f.Darwin != nil:
|
||||
return f.Darwin.Xattrs
|
||||
case build.IsFreeBSD && f.FreeBSD != nil:
|
||||
return f.FreeBSD.Xattrs
|
||||
case build.IsNetBSD && f.NetBSD != nil:
|
||||
return f.NetBSD.Xattrs
|
||||
case build.IsLinux && p.Linux != nil:
|
||||
return p.Linux.Xattrs
|
||||
case build.IsDarwin && p.Darwin != nil:
|
||||
return p.Darwin.Xattrs
|
||||
case build.IsFreeBSD && p.FreeBSD != nil:
|
||||
return p.FreeBSD.Xattrs
|
||||
case build.IsNetBSD && p.NetBSD != nil:
|
||||
return p.NetBSD.Xattrs
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
@@ -422,119 +700,122 @@ func blocksEqual(a, b []BlockInfo) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (f *FileInfo) SetMustRescan() {
|
||||
f.setLocalFlags(FlagLocalMustRescan)
|
||||
type PlatformData struct {
|
||||
Unix *UnixData
|
||||
Windows *WindowsData
|
||||
Linux *XattrData
|
||||
Darwin *XattrData
|
||||
FreeBSD *XattrData
|
||||
NetBSD *XattrData
|
||||
}
|
||||
|
||||
func (f *FileInfo) SetIgnored() {
|
||||
f.setLocalFlags(FlagLocalIgnored)
|
||||
}
|
||||
|
||||
func (f *FileInfo) SetUnsupported() {
|
||||
f.setLocalFlags(FlagLocalUnsupported)
|
||||
}
|
||||
|
||||
func (f *FileInfo) SetDeleted(by ShortID) {
|
||||
f.ModifiedBy = by
|
||||
f.Deleted = true
|
||||
f.Version = f.Version.Update(by)
|
||||
f.ModifiedS = time.Now().Unix()
|
||||
f.setNoContent()
|
||||
}
|
||||
|
||||
func (f *FileInfo) setLocalFlags(flags uint32) {
|
||||
f.RawInvalid = false
|
||||
f.LocalFlags = flags
|
||||
f.setNoContent()
|
||||
}
|
||||
|
||||
func (f *FileInfo) setNoContent() {
|
||||
f.Blocks = nil
|
||||
f.BlocksHash = nil
|
||||
f.Size = 0
|
||||
}
|
||||
|
||||
func (b BlockInfo) String() string {
|
||||
return fmt.Sprintf("Block{%d/%d/%d/%x}", b.Offset, b.Size, b.WeakHash, b.Hash)
|
||||
}
|
||||
|
||||
// IsEmpty returns true if the block is a full block of zeroes.
|
||||
func (b BlockInfo) IsEmpty() bool {
|
||||
if v, ok := sha256OfEmptyBlock[int(b.Size)]; ok {
|
||||
return bytes.Equal(b.Hash, v[:])
|
||||
func (p *PlatformData) toWire() *bep.PlatformData {
|
||||
return &bep.PlatformData{
|
||||
Unix: p.Unix.toWire(),
|
||||
Windows: p.Windows,
|
||||
Linux: p.Linux.toWire(),
|
||||
Darwin: p.Darwin.toWire(),
|
||||
Freebsd: p.FreeBSD.toWire(),
|
||||
Netbsd: p.NetBSD.toWire(),
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type IndexID uint64
|
||||
|
||||
func (i IndexID) String() string {
|
||||
return fmt.Sprintf("0x%016X", uint64(i))
|
||||
}
|
||||
|
||||
func (i IndexID) Marshal() ([]byte, error) {
|
||||
bs := make([]byte, 8)
|
||||
binary.BigEndian.PutUint64(bs, uint64(i))
|
||||
return bs, nil
|
||||
}
|
||||
|
||||
func (i *IndexID) Unmarshal(bs []byte) error {
|
||||
if len(bs) != 8 {
|
||||
return errors.New("incorrect IndexID length")
|
||||
func platformDataFromWire(w *bep.PlatformData) PlatformData {
|
||||
if w == nil {
|
||||
return PlatformData{}
|
||||
}
|
||||
*i = IndexID(binary.BigEndian.Uint64(bs))
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewIndexID() IndexID {
|
||||
return IndexID(rand.Uint64())
|
||||
}
|
||||
|
||||
func (f Folder) Description() string {
|
||||
// used by logging stuff
|
||||
if f.Label == "" {
|
||||
return f.ID
|
||||
return PlatformData{
|
||||
Unix: unixDataFromWire(w.Unix),
|
||||
Windows: w.Windows,
|
||||
Linux: xattrDataFromWire(w.Linux),
|
||||
Darwin: xattrDataFromWire(w.Darwin),
|
||||
FreeBSD: xattrDataFromWire(w.Freebsd),
|
||||
NetBSD: xattrDataFromWire(w.Netbsd),
|
||||
}
|
||||
return fmt.Sprintf("%q (%s)", f.Label, f.ID)
|
||||
}
|
||||
|
||||
func BlocksHash(bs []BlockInfo) []byte {
|
||||
h := sha256.New()
|
||||
for _, b := range bs {
|
||||
_, _ = h.Write(b.Hash)
|
||||
_ = binary.Write(h, binary.BigEndian, b.WeakHash)
|
||||
}
|
||||
return h.Sum(nil)
|
||||
type UnixData struct {
|
||||
// The owner name and group name are set when known (i.e., could be
|
||||
// resolved on the source device), while the UID and GID are always set
|
||||
// as they come directly from the stat() call.
|
||||
OwnerName string
|
||||
GroupName string
|
||||
UID int
|
||||
GID int
|
||||
}
|
||||
|
||||
func VectorHash(v Vector) []byte {
|
||||
h := sha256.New()
|
||||
for _, c := range v.Counters {
|
||||
if err := binary.Write(h, binary.BigEndian, c.ID); err != nil {
|
||||
panic("impossible: failed to write c.ID to hash function: " + err.Error())
|
||||
}
|
||||
if err := binary.Write(h, binary.BigEndian, c.Value); err != nil {
|
||||
panic("impossible: failed to write c.Value to hash function: " + err.Error())
|
||||
}
|
||||
func (u *UnixData) toWire() *bep.UnixData {
|
||||
if u == nil {
|
||||
return nil
|
||||
}
|
||||
return &bep.UnixData{
|
||||
OwnerName: u.OwnerName,
|
||||
GroupName: u.GroupName,
|
||||
Uid: int32(u.UID),
|
||||
Gid: int32(u.GID),
|
||||
}
|
||||
return h.Sum(nil)
|
||||
}
|
||||
|
||||
func (x *FileInfoType) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(x.String())
|
||||
func unixDataFromWire(w *bep.UnixData) *UnixData {
|
||||
if w == nil {
|
||||
return nil
|
||||
}
|
||||
return &UnixData{
|
||||
OwnerName: w.OwnerName,
|
||||
GroupName: w.GroupName,
|
||||
UID: int(w.Uid),
|
||||
GID: int(w.Gid),
|
||||
}
|
||||
}
|
||||
|
||||
func (x *FileInfoType) UnmarshalJSON(data []byte) error {
|
||||
var s string
|
||||
if err := json.Unmarshal(data, &s); err != nil {
|
||||
return err
|
||||
type WindowsData = bep.WindowsData
|
||||
|
||||
type XattrData struct {
|
||||
Xattrs []Xattr
|
||||
}
|
||||
|
||||
func (x *XattrData) toWire() *bep.XattrData {
|
||||
if x == nil {
|
||||
return nil
|
||||
}
|
||||
n, ok := FileInfoType_value[s]
|
||||
if !ok {
|
||||
return errors.New("invalid value: " + s)
|
||||
xattrs := make([]*bep.Xattr, len(x.Xattrs))
|
||||
for i, a := range x.Xattrs {
|
||||
xattrs[i] = a.toWire()
|
||||
}
|
||||
return &bep.XattrData{
|
||||
Xattrs: xattrs,
|
||||
}
|
||||
}
|
||||
|
||||
func xattrDataFromWire(w *bep.XattrData) *XattrData {
|
||||
if w == nil {
|
||||
return nil
|
||||
}
|
||||
x := &XattrData{}
|
||||
x.Xattrs = make([]Xattr, len(w.Xattrs))
|
||||
for i, a := range w.Xattrs {
|
||||
x.Xattrs[i] = xattrFromWire(a)
|
||||
}
|
||||
return x
|
||||
}
|
||||
|
||||
type Xattr struct {
|
||||
Name string
|
||||
Value []byte
|
||||
}
|
||||
|
||||
func (a Xattr) toWire() *bep.Xattr {
|
||||
return &bep.Xattr{
|
||||
Name: a.Name,
|
||||
Value: a.Value,
|
||||
}
|
||||
}
|
||||
|
||||
func xattrFromWire(w *bep.Xattr) Xattr {
|
||||
return Xattr{
|
||||
Name: w.Name,
|
||||
Value: w.Value,
|
||||
}
|
||||
*x = FileInfoType(n)
|
||||
return nil
|
||||
}
|
||||
|
||||
func xattrsEqual(a, b *XattrData) bool {
|
||||
@@ -0,0 +1,293 @@
|
||||
// Copyright (C) 2014 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 protocol
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"testing"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/build"
|
||||
)
|
||||
|
||||
func TestLocalFlagBits(t *testing.T) {
|
||||
var f FileInfo
|
||||
if f.IsIgnored() || f.MustRescan() || f.IsInvalid() {
|
||||
t.Error("file should have no weird bits set by default")
|
||||
}
|
||||
|
||||
f.SetIgnored()
|
||||
if !f.IsIgnored() || f.MustRescan() || !f.IsInvalid() {
|
||||
t.Error("file should be ignored and invalid")
|
||||
}
|
||||
|
||||
f.SetMustRescan()
|
||||
if f.IsIgnored() || !f.MustRescan() || !f.IsInvalid() {
|
||||
t.Error("file should be must-rescan and invalid")
|
||||
}
|
||||
|
||||
f.SetUnsupported()
|
||||
if f.IsIgnored() || f.MustRescan() || !f.IsInvalid() {
|
||||
t.Error("file should be invalid")
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsEquivalent(t *testing.T) {
|
||||
b := func(v bool) *bool {
|
||||
return &v
|
||||
}
|
||||
|
||||
type testCase struct {
|
||||
a FileInfo
|
||||
b FileInfo
|
||||
ignPerms *bool // nil means should not matter, we'll test both variants
|
||||
ignBlocks *bool
|
||||
ignFlags uint32
|
||||
eq bool
|
||||
}
|
||||
cases := []testCase{
|
||||
// Empty FileInfos are equivalent
|
||||
{eq: true},
|
||||
|
||||
// Various basic attributes, all of which cause inequality when
|
||||
// they differ
|
||||
{
|
||||
a: FileInfo{Name: "foo"},
|
||||
b: FileInfo{Name: "bar"},
|
||||
eq: false,
|
||||
},
|
||||
{
|
||||
a: FileInfo{Type: FileInfoTypeFile},
|
||||
b: FileInfo{Type: FileInfoTypeDirectory},
|
||||
eq: false,
|
||||
},
|
||||
{
|
||||
a: FileInfo{Size: 1234},
|
||||
b: FileInfo{Size: 2345},
|
||||
eq: false,
|
||||
},
|
||||
{
|
||||
a: FileInfo{Deleted: false},
|
||||
b: FileInfo{Deleted: true},
|
||||
eq: false,
|
||||
},
|
||||
{
|
||||
a: FileInfo{RawInvalid: false},
|
||||
b: FileInfo{RawInvalid: true},
|
||||
eq: false,
|
||||
},
|
||||
{
|
||||
a: FileInfo{ModifiedS: 1234},
|
||||
b: FileInfo{ModifiedS: 2345},
|
||||
eq: false,
|
||||
},
|
||||
{
|
||||
a: FileInfo{ModifiedNs: 1234},
|
||||
b: FileInfo{ModifiedNs: 2345},
|
||||
eq: false,
|
||||
},
|
||||
|
||||
// Special handling of local flags and invalidity. "MustRescan"
|
||||
// files are never equivalent to each other. Otherwise, equivalence
|
||||
// is based just on whether the file becomes IsInvalid() or not, not
|
||||
// the specific reason or flag bits.
|
||||
{
|
||||
a: FileInfo{LocalFlags: FlagLocalMustRescan},
|
||||
b: FileInfo{LocalFlags: FlagLocalMustRescan},
|
||||
eq: false,
|
||||
},
|
||||
{
|
||||
a: FileInfo{RawInvalid: true},
|
||||
b: FileInfo{RawInvalid: true},
|
||||
eq: true,
|
||||
},
|
||||
{
|
||||
a: FileInfo{LocalFlags: FlagLocalUnsupported},
|
||||
b: FileInfo{LocalFlags: FlagLocalUnsupported},
|
||||
eq: true,
|
||||
},
|
||||
{
|
||||
a: FileInfo{RawInvalid: true},
|
||||
b: FileInfo{LocalFlags: FlagLocalUnsupported},
|
||||
eq: true,
|
||||
},
|
||||
{
|
||||
a: FileInfo{LocalFlags: 0},
|
||||
b: FileInfo{LocalFlags: FlagLocalReceiveOnly},
|
||||
eq: false,
|
||||
},
|
||||
{
|
||||
a: FileInfo{LocalFlags: 0},
|
||||
b: FileInfo{LocalFlags: FlagLocalReceiveOnly},
|
||||
ignFlags: FlagLocalReceiveOnly,
|
||||
eq: true,
|
||||
},
|
||||
|
||||
// Difference in blocks is not OK
|
||||
{
|
||||
a: FileInfo{Blocks: []BlockInfo{{Hash: []byte{1, 2, 3, 4}}}},
|
||||
b: FileInfo{Blocks: []BlockInfo{{Hash: []byte{2, 3, 4, 5}}}},
|
||||
ignBlocks: b(false),
|
||||
eq: false,
|
||||
},
|
||||
|
||||
// ... unless we say it is
|
||||
{
|
||||
a: FileInfo{Blocks: []BlockInfo{{Hash: []byte{1, 2, 3, 4}}}},
|
||||
b: FileInfo{Blocks: []BlockInfo{{Hash: []byte{2, 3, 4, 5}}}},
|
||||
ignBlocks: b(true),
|
||||
eq: true,
|
||||
},
|
||||
|
||||
// Difference in permissions is not OK.
|
||||
{
|
||||
a: FileInfo{Permissions: 0o444},
|
||||
b: FileInfo{Permissions: 0o666},
|
||||
ignPerms: b(false),
|
||||
eq: false,
|
||||
},
|
||||
|
||||
// ... unless we say it is
|
||||
{
|
||||
a: FileInfo{Permissions: 0o666},
|
||||
b: FileInfo{Permissions: 0o444},
|
||||
ignPerms: b(true),
|
||||
eq: true,
|
||||
},
|
||||
|
||||
// These attributes are not checked at all
|
||||
{
|
||||
a: FileInfo{NoPermissions: false},
|
||||
b: FileInfo{NoPermissions: true},
|
||||
eq: true,
|
||||
},
|
||||
{
|
||||
a: FileInfo{Version: Vector{Counters: []Counter{{ID: 1, Value: 42}}}},
|
||||
b: FileInfo{Version: Vector{Counters: []Counter{{ID: 42, Value: 1}}}},
|
||||
eq: true,
|
||||
},
|
||||
{
|
||||
a: FileInfo{Sequence: 1},
|
||||
b: FileInfo{Sequence: 2},
|
||||
eq: true,
|
||||
},
|
||||
|
||||
// The block size is not checked (but this would fail the blocks
|
||||
// check in real world)
|
||||
{
|
||||
a: FileInfo{RawBlockSize: 1},
|
||||
b: FileInfo{RawBlockSize: 2},
|
||||
eq: true,
|
||||
},
|
||||
|
||||
// The symlink target is checked for symlinks
|
||||
{
|
||||
a: FileInfo{Type: FileInfoTypeSymlink, SymlinkTarget: "a"},
|
||||
b: FileInfo{Type: FileInfoTypeSymlink, SymlinkTarget: "b"},
|
||||
eq: false,
|
||||
},
|
||||
|
||||
// ... but not for non-symlinks
|
||||
{
|
||||
a: FileInfo{Type: FileInfoTypeFile, SymlinkTarget: "a"},
|
||||
b: FileInfo{Type: FileInfoTypeFile, SymlinkTarget: "b"},
|
||||
eq: true,
|
||||
},
|
||||
}
|
||||
|
||||
if build.IsWindows {
|
||||
// On windows we only check the user writable bit of the permission
|
||||
// set, so these are equivalent.
|
||||
cases = append(cases, testCase{
|
||||
a: FileInfo{Permissions: 0o777},
|
||||
b: FileInfo{Permissions: 0o600},
|
||||
ignPerms: b(false),
|
||||
eq: true,
|
||||
})
|
||||
}
|
||||
|
||||
for i, tc := range cases {
|
||||
// Check the standard attributes with all permutations of the
|
||||
// special ignore flags, unless the value of those flags are given
|
||||
// in the tests.
|
||||
for _, ignPerms := range []bool{true, false} {
|
||||
for _, ignBlocks := range []bool{true, false} {
|
||||
if tc.ignPerms != nil && *tc.ignPerms != ignPerms {
|
||||
continue
|
||||
}
|
||||
if tc.ignBlocks != nil && *tc.ignBlocks != ignBlocks {
|
||||
continue
|
||||
}
|
||||
|
||||
if res := tc.a.isEquivalent(tc.b, FileInfoComparison{IgnorePerms: ignPerms, IgnoreBlocks: ignBlocks, IgnoreFlags: tc.ignFlags}); res != tc.eq {
|
||||
t.Errorf("Case %d:\na: %v\nb: %v\na.IsEquivalent(b, %v, %v) => %v, expected %v", i, tc.a, tc.b, ignPerms, ignBlocks, res, tc.eq)
|
||||
}
|
||||
if res := tc.b.isEquivalent(tc.a, FileInfoComparison{IgnorePerms: ignPerms, IgnoreBlocks: ignBlocks, IgnoreFlags: tc.ignFlags}); res != tc.eq {
|
||||
t.Errorf("Case %d:\na: %v\nb: %v\nb.IsEquivalent(a, %v, %v) => %v, expected %v", i, tc.a, tc.b, ignPerms, ignBlocks, res, tc.eq)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSha256OfEmptyBlock(t *testing.T) {
|
||||
// every block size should have a correct entry in sha256OfEmptyBlock
|
||||
for blockSize := MinBlockSize; blockSize <= MaxBlockSize; blockSize *= 2 {
|
||||
expected := sha256.Sum256(make([]byte, blockSize))
|
||||
if sha256OfEmptyBlock[blockSize] != expected {
|
||||
t.Error("missing or wrong hash for block of size", blockSize)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBlocksEqual(t *testing.T) {
|
||||
blocksOne := []BlockInfo{{Hash: []byte{1, 2, 3, 4}}}
|
||||
blocksTwo := []BlockInfo{{Hash: []byte{5, 6, 7, 8}}}
|
||||
hashOne := []byte{42, 42, 42, 42}
|
||||
hashTwo := []byte{29, 29, 29, 29}
|
||||
|
||||
cases := []struct {
|
||||
b1 []BlockInfo
|
||||
h1 []byte
|
||||
b2 []BlockInfo
|
||||
h2 []byte
|
||||
eq bool
|
||||
}{
|
||||
{blocksOne, hashOne, blocksOne, hashOne, true}, // everything equal
|
||||
{blocksOne, hashOne, blocksTwo, hashTwo, false}, // nothing equal
|
||||
{blocksOne, hashOne, blocksOne, nil, true}, // blocks compared
|
||||
{blocksOne, nil, blocksOne, nil, true}, // blocks compared
|
||||
{blocksOne, nil, blocksTwo, nil, false}, // blocks compared
|
||||
{blocksOne, hashOne, blocksTwo, hashOne, true}, // hashes equal, blocks not looked at
|
||||
{blocksOne, hashOne, blocksOne, hashTwo, true}, // hashes different, blocks compared
|
||||
{blocksOne, hashOne, blocksTwo, hashTwo, false}, // hashes different, blocks compared
|
||||
{blocksOne, hashOne, nil, nil, false}, // blocks is different from no blocks
|
||||
{blocksOne, nil, nil, nil, false}, // blocks is different from no blocks
|
||||
{nil, hashOne, nil, nil, true}, // nil blocks are equal, even of one side has a hash
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
f1 := FileInfo{Blocks: tc.b1, BlocksHash: tc.h1}
|
||||
f2 := FileInfo{Blocks: tc.b2, BlocksHash: tc.h2}
|
||||
|
||||
if !f1.BlocksEqual(f1) {
|
||||
t.Error("f1 is always equal to itself", f1)
|
||||
}
|
||||
if !f2.BlocksEqual(f2) {
|
||||
t.Error("f2 is always equal to itself", f2)
|
||||
}
|
||||
if res := f1.BlocksEqual(f2); res != tc.eq {
|
||||
t.Log("f1", f1.BlocksHash, f1.Blocks)
|
||||
t.Log("f2", f2.BlocksHash, f2.Blocks)
|
||||
t.Errorf("f1.BlocksEqual(f2) == %v but should be %v", res, tc.eq)
|
||||
}
|
||||
if res := f2.BlocksEqual(f1); res != tc.eq {
|
||||
t.Log("f1", f1.BlocksHash, f1.Blocks)
|
||||
t.Log("f2", f2.BlocksHash, f2.Blocks)
|
||||
t.Errorf("f2.BlocksEqual(f1) == %v but should be %v", res, tc.eq)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,8 @@
|
||||
// Copyright (C) 2016 The Protocol Authors.
|
||||
// Copyright (C) 2016 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 protocol
|
||||
|
||||
@@ -6,6 +10,15 @@ import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
"github.com/syncthing/syncthing/internal/gen/bep"
|
||||
)
|
||||
|
||||
const (
|
||||
HelloMessageMagic uint32 = 0x2EA7D90B
|
||||
Version13HelloMagic uint32 = 0x9F79BC40 // old
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -17,6 +30,38 @@ var (
|
||||
ErrUnknownMagic = errors.New("the remote device speaks an unknown (newer?) version of the protocol")
|
||||
)
|
||||
|
||||
type Hello struct {
|
||||
DeviceName string
|
||||
ClientName string
|
||||
ClientVersion string
|
||||
NumConnections int
|
||||
Timestamp int64
|
||||
}
|
||||
|
||||
func (h *Hello) toWire() *bep.Hello {
|
||||
return &bep.Hello{
|
||||
DeviceName: h.DeviceName,
|
||||
ClientName: h.ClientName,
|
||||
ClientVersion: h.ClientVersion,
|
||||
NumConnections: int32(h.NumConnections),
|
||||
Timestamp: h.Timestamp,
|
||||
}
|
||||
}
|
||||
|
||||
func helloFromWire(w *bep.Hello) Hello {
|
||||
return Hello{
|
||||
DeviceName: w.DeviceName,
|
||||
ClientName: w.ClientName,
|
||||
ClientVersion: w.ClientVersion,
|
||||
NumConnections: int(w.NumConnections),
|
||||
Timestamp: w.Timestamp,
|
||||
}
|
||||
}
|
||||
|
||||
func (Hello) Magic() uint32 {
|
||||
return HelloMessageMagic
|
||||
}
|
||||
|
||||
func ExchangeHello(c io.ReadWriter, h Hello) (Hello, error) {
|
||||
if h.Timestamp == 0 {
|
||||
panic("bug: missing timestamp in outgoing hello")
|
||||
@@ -30,12 +75,7 @@ func ExchangeHello(c io.ReadWriter, h Hello) (Hello, error) {
|
||||
// IsVersionMismatch returns true if the error is a reliable indication of a
|
||||
// version mismatch that we might want to alert the user about.
|
||||
func IsVersionMismatch(err error) bool {
|
||||
switch err {
|
||||
case ErrTooOldVersion, ErrUnknownMagic:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
return errors.Is(err, ErrTooOldVersion) || errors.Is(err, ErrUnknownMagic)
|
||||
}
|
||||
|
||||
func readHello(c io.Reader) (Hello, error) {
|
||||
@@ -59,11 +99,12 @@ func readHello(c io.Reader) (Hello, error) {
|
||||
return Hello{}, err
|
||||
}
|
||||
|
||||
var hello Hello
|
||||
if err := hello.Unmarshal(buf); err != nil {
|
||||
var wh bep.Hello
|
||||
if err := proto.Unmarshal(buf, &wh); err != nil {
|
||||
return Hello{}, err
|
||||
}
|
||||
return Hello(hello), nil
|
||||
|
||||
return helloFromWire(&wh), nil
|
||||
|
||||
case 0x00010001, 0x00010000, Version13HelloMagic:
|
||||
// This is the first word of an older cluster config message or an
|
||||
@@ -76,7 +117,7 @@ func readHello(c io.Reader) (Hello, error) {
|
||||
}
|
||||
|
||||
func writeHello(c io.Writer, h Hello) error {
|
||||
msg, err := h.Marshal()
|
||||
msg, err := proto.Marshal(h.toWire())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1,4 +1,8 @@
|
||||
// Copyright (C) 2016 The Protocol Authors.
|
||||
// Copyright (C) 2016 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 protocol
|
||||
|
||||
@@ -8,6 +12,8 @@ import (
|
||||
"encoding/hex"
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
func TestVersion14Hello(t *testing.T) {
|
||||
@@ -18,7 +24,7 @@ func TestVersion14Hello(t *testing.T) {
|
||||
ClientName: "syncthing",
|
||||
ClientVersion: "v0.14.5",
|
||||
}
|
||||
msgBuf, err := expected.Marshal()
|
||||
msgBuf, err := proto.Marshal(expected.toWire())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
// Copyright (C) 2014 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 protocol
|
||||
|
||||
import "github.com/syncthing/syncthing/internal/gen/bep"
|
||||
|
||||
type Index struct {
|
||||
Folder string
|
||||
Files []FileInfo
|
||||
LastSequence int64
|
||||
}
|
||||
|
||||
func (i *Index) toWire() *bep.Index {
|
||||
files := make([]*bep.FileInfo, len(i.Files))
|
||||
for j, f := range i.Files {
|
||||
files[j] = f.ToWire(false)
|
||||
}
|
||||
return &bep.Index{
|
||||
Folder: i.Folder,
|
||||
Files: files,
|
||||
LastSequence: i.LastSequence,
|
||||
}
|
||||
}
|
||||
|
||||
func indexFromWire(w *bep.Index) *Index {
|
||||
if w == nil {
|
||||
return nil
|
||||
}
|
||||
i := &Index{
|
||||
Folder: w.Folder,
|
||||
LastSequence: w.LastSequence,
|
||||
}
|
||||
i.Files = make([]FileInfo, len(w.Files))
|
||||
for j, f := range w.Files {
|
||||
i.Files[j] = FileInfoFromWire(f)
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
type IndexUpdate struct {
|
||||
Folder string
|
||||
Files []FileInfo
|
||||
LastSequence int64
|
||||
PrevSequence int64
|
||||
}
|
||||
|
||||
func (i *IndexUpdate) toWire() *bep.IndexUpdate {
|
||||
files := make([]*bep.FileInfo, len(i.Files))
|
||||
for j, f := range i.Files {
|
||||
files[j] = f.ToWire(false)
|
||||
}
|
||||
return &bep.IndexUpdate{
|
||||
Folder: i.Folder,
|
||||
Files: files,
|
||||
LastSequence: i.LastSequence,
|
||||
PrevSequence: i.PrevSequence,
|
||||
}
|
||||
}
|
||||
|
||||
func indexUpdateFromWire(w *bep.IndexUpdate) *IndexUpdate {
|
||||
if w == nil {
|
||||
return nil
|
||||
}
|
||||
i := &IndexUpdate{
|
||||
Folder: w.Folder,
|
||||
LastSequence: w.LastSequence,
|
||||
PrevSequence: w.PrevSequence,
|
||||
}
|
||||
i.Files = make([]FileInfo, len(w.Files))
|
||||
for j, f := range w.Files {
|
||||
i.Files[j] = FileInfoFromWire(f)
|
||||
}
|
||||
return i
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
// Copyright (C) 2014 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 protocol
|
||||
|
||||
import "github.com/syncthing/syncthing/internal/gen/bep"
|
||||
|
||||
type ErrorCode = bep.ErrorCode
|
||||
|
||||
const (
|
||||
ErrorCodeNoError = bep.ErrorCode_ERROR_CODE_NO_ERROR
|
||||
ErrorCodeGeneric = bep.ErrorCode_ERROR_CODE_GENERIC
|
||||
ErrorCodeNoSuchFile = bep.ErrorCode_ERROR_CODE_NO_SUCH_FILE
|
||||
ErrorCodeInvalidFile = bep.ErrorCode_ERROR_CODE_INVALID_FILE
|
||||
)
|
||||
|
||||
type Request struct {
|
||||
ID int
|
||||
Folder string
|
||||
Name string
|
||||
Offset int64
|
||||
Size int
|
||||
Hash []byte
|
||||
FromTemporary bool
|
||||
WeakHash uint32
|
||||
BlockNo int
|
||||
}
|
||||
|
||||
func (r *Request) toWire() *bep.Request {
|
||||
return &bep.Request{
|
||||
Id: int32(r.ID),
|
||||
Folder: r.Folder,
|
||||
Name: r.Name,
|
||||
Offset: r.Offset,
|
||||
Size: int32(r.Size),
|
||||
Hash: r.Hash,
|
||||
FromTemporary: r.FromTemporary,
|
||||
WeakHash: r.WeakHash,
|
||||
BlockNo: int32(r.BlockNo),
|
||||
}
|
||||
}
|
||||
|
||||
func requestFromWire(w *bep.Request) *Request {
|
||||
return &Request{
|
||||
ID: int(w.Id),
|
||||
Folder: w.Folder,
|
||||
Name: w.Name,
|
||||
Offset: w.Offset,
|
||||
Size: int(w.Size),
|
||||
Hash: w.Hash,
|
||||
FromTemporary: w.FromTemporary,
|
||||
WeakHash: w.WeakHash,
|
||||
BlockNo: int(w.BlockNo),
|
||||
}
|
||||
}
|
||||
|
||||
type Response struct {
|
||||
ID int
|
||||
Data []byte
|
||||
Code ErrorCode
|
||||
}
|
||||
|
||||
func (r *Response) toWire() *bep.Response {
|
||||
return &bep.Response{
|
||||
Id: int32(r.ID),
|
||||
Data: r.Data,
|
||||
Code: r.Code,
|
||||
}
|
||||
}
|
||||
|
||||
func responseFromWire(w *bep.Response) *Response {
|
||||
return &Response{
|
||||
ID: int(w.Id),
|
||||
Data: w.Data,
|
||||
Code: w.Code,
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user