Add LocalFlags to FileInfo (#4952)
We have the invalid bit to indicate that a file isn't good. That's enough for remote devices. For ourselves, it would be good to know sometimes why the file isn't good - because it's an unsupported type, because it matches an ignore pattern, or because we detected the data is bad and we need to rescan it. Or, and this is the main future reason for the PR, because it's a change detected on a receive only device. We will want something like the invalid flag for those changes, but marking them as invalid today means the scanner will rehash them. Hence something more fine grained is required. This introduces a LocalFlags fields to the FileInfo where we can stash things that we care about locally. For example, 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 The LocalFlags fields isn't sent over the wire; instead the Invalid attribute is calculated based on the flags at index sending time. It's on the FileInfo anyway because that's what we serialize to database etc. The actual Invalid flag should after this just be considered when building the global state and figuring out availability for remote devices. It is not used for local file index entries.
This commit is contained in:
parent
6df3940c26
commit
b1b68ceedb
|
@ -1497,13 +1497,16 @@ func (f jsonFileInfo) MarshalJSON() ([]byte, error) {
|
||||||
"size": f.Size,
|
"size": f.Size,
|
||||||
"permissions": fmt.Sprintf("%#o", f.Permissions),
|
"permissions": fmt.Sprintf("%#o", f.Permissions),
|
||||||
"deleted": f.Deleted,
|
"deleted": f.Deleted,
|
||||||
"invalid": f.Invalid,
|
"invalid": protocol.FileInfo(f).IsInvalid(),
|
||||||
|
"ignored": protocol.FileInfo(f).IsIgnored(),
|
||||||
|
"mustRescan": protocol.FileInfo(f).MustRescan(),
|
||||||
"noPermissions": f.NoPermissions,
|
"noPermissions": f.NoPermissions,
|
||||||
"modified": protocol.FileInfo(f).ModTime(),
|
"modified": protocol.FileInfo(f).ModTime(),
|
||||||
"modifiedBy": f.ModifiedBy.String(),
|
"modifiedBy": f.ModifiedBy.String(),
|
||||||
"sequence": f.Sequence,
|
"sequence": f.Sequence,
|
||||||
"numBlocks": len(f.Blocks),
|
"numBlocks": len(f.Blocks),
|
||||||
"version": jsonVersionVector(f.Version),
|
"version": jsonVersionVector(f.Version),
|
||||||
|
"localFlags": f.LocalFlags,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1516,11 +1519,16 @@ func (f jsonDBFileInfo) MarshalJSON() ([]byte, error) {
|
||||||
"size": f.Size,
|
"size": f.Size,
|
||||||
"permissions": fmt.Sprintf("%#o", f.Permissions),
|
"permissions": fmt.Sprintf("%#o", f.Permissions),
|
||||||
"deleted": f.Deleted,
|
"deleted": f.Deleted,
|
||||||
"invalid": f.Invalid,
|
"invalid": db.FileInfoTruncated(f).IsInvalid(),
|
||||||
|
"ignored": db.FileInfoTruncated(f).IsIgnored(),
|
||||||
|
"mustRescan": db.FileInfoTruncated(f).MustRescan(),
|
||||||
"noPermissions": f.NoPermissions,
|
"noPermissions": f.NoPermissions,
|
||||||
"modified": db.FileInfoTruncated(f).ModTime(),
|
"modified": db.FileInfoTruncated(f).ModTime(),
|
||||||
"modifiedBy": f.ModifiedBy.String(),
|
"modifiedBy": f.ModifiedBy.String(),
|
||||||
"sequence": f.Sequence,
|
"sequence": f.Sequence,
|
||||||
|
"numBlocks": nil, // explicitly unknown
|
||||||
|
"version": jsonVersionVector(f.Version),
|
||||||
|
"localFlags": f.LocalFlags,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -96,11 +96,8 @@ func TestBlockMapAddUpdateWipe(t *testing.T) {
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
f3.Permissions = f1.Permissions
|
|
||||||
f3.Deleted = f1.Deleted
|
|
||||||
f3.Invalid = f1.Invalid
|
|
||||||
f1.Deleted = true
|
f1.Deleted = true
|
||||||
f2.Invalid = true
|
f2.LocalFlags = protocol.FlagLocalMustRescan // one of the invalid markers
|
||||||
|
|
||||||
// Should remove
|
// Should remove
|
||||||
err = m.Update([]protocol.FileInfo{f1, f2, f3})
|
err = m.Update([]protocol.FileInfo{f1, f2, f3})
|
||||||
|
@ -145,14 +142,11 @@ func TestBlockMapAddUpdateWipe(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
f1.Deleted = false
|
f1.Deleted = false
|
||||||
f1.Invalid = false
|
f1.LocalFlags = 0
|
||||||
f1.Permissions = 0
|
|
||||||
f2.Deleted = false
|
f2.Deleted = false
|
||||||
f2.Invalid = false
|
f2.LocalFlags = 0
|
||||||
f2.Permissions = 0
|
|
||||||
f3.Deleted = false
|
f3.Deleted = false
|
||||||
f3.Invalid = false
|
f3.LocalFlags = 0
|
||||||
f3.Permissions = 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBlockFinderLookup(t *testing.T) {
|
func TestBlockFinderLookup(t *testing.T) {
|
||||||
|
|
|
@ -61,7 +61,7 @@ func (vl VersionList) update(folder, device []byte, file protocol.FileInfo, db *
|
||||||
nv := FileVersion{
|
nv := FileVersion{
|
||||||
Device: device,
|
Device: device,
|
||||||
Version: file.Version,
|
Version: file.Version,
|
||||||
Invalid: file.Invalid,
|
Invalid: file.IsInvalid(),
|
||||||
}
|
}
|
||||||
for i, v := range vl.Versions {
|
for i, v := range vl.Versions {
|
||||||
switch v.Version.Compare(file.Version) {
|
switch v.Version.Compare(file.Version) {
|
||||||
|
|
|
@ -115,8 +115,9 @@ func (db *Instance) updateFiles(folder, device []byte, fs []protocol.FileInfo, m
|
||||||
err = ef.Unmarshal(bs)
|
err = ef.Unmarshal(bs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The Invalid flag might change without the version being bumped.
|
// Local flags or the invalid bit might change without the version
|
||||||
if err == nil && ef.Version.Equal(f.Version) && ef.Invalid == f.Invalid {
|
// being bumped. The IsInvalid() method handles both.
|
||||||
|
if err == nil && ef.Version.Equal(f.Version) && ef.IsInvalid() == f.IsInvalid() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ import (
|
||||||
"github.com/syndtr/goleveldb/leveldb/util"
|
"github.com/syndtr/goleveldb/leveldb/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
const dbVersion = 4
|
const dbVersion = 5
|
||||||
|
|
||||||
func (db *Instance) updateSchema() {
|
func (db *Instance) updateSchema() {
|
||||||
miscDB := NewNamespacedKV(db, string(KeyTypeMiscData))
|
miscDB := NewNamespacedKV(db, string(KeyTypeMiscData))
|
||||||
|
@ -23,8 +23,6 @@ func (db *Instance) updateSchema() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
l.Infof("Updating database schema version from %v to %v...", prevVersion, dbVersion)
|
|
||||||
|
|
||||||
if prevVersion < 1 {
|
if prevVersion < 1 {
|
||||||
db.updateSchema0to1()
|
db.updateSchema0to1()
|
||||||
}
|
}
|
||||||
|
@ -38,6 +36,9 @@ func (db *Instance) updateSchema() {
|
||||||
if prevVersion == 3 {
|
if prevVersion == 3 {
|
||||||
db.updateSchema3to4()
|
db.updateSchema3to4()
|
||||||
}
|
}
|
||||||
|
if prevVersion < 5 {
|
||||||
|
db.updateSchema4to5()
|
||||||
|
}
|
||||||
|
|
||||||
miscDB.PutInt64("dbVersion", dbVersion)
|
miscDB.PutInt64("dbVersion", dbVersion)
|
||||||
}
|
}
|
||||||
|
@ -94,7 +95,7 @@ func (db *Instance) updateSchema0to1() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add invalid files to global list
|
// Add invalid files to global list
|
||||||
if f.Invalid {
|
if f.IsInvalid() {
|
||||||
gk = db.globalKeyInto(gk, folder, name)
|
gk = db.globalKeyInto(gk, folder, name)
|
||||||
if t.updateGlobal(gk, folder, device, f, meta) {
|
if t.updateGlobal(gk, folder, device, f, meta) {
|
||||||
if _, ok := changedFolders[string(folder)]; !ok {
|
if _, ok := changedFolders[string(folder)]; !ok {
|
||||||
|
@ -172,3 +173,33 @@ func (db *Instance) updateSchema3to4() {
|
||||||
|
|
||||||
db.updateSchema2to3()
|
db.updateSchema2to3()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (db *Instance) updateSchema4to5() {
|
||||||
|
// For every local file with the Invalid bit set, clear the Invalid bit and
|
||||||
|
// set LocalFlags = FlagLocalIgnored.
|
||||||
|
|
||||||
|
t := db.newReadWriteTransaction()
|
||||||
|
defer t.close()
|
||||||
|
|
||||||
|
var dk []byte
|
||||||
|
|
||||||
|
for _, folderStr := range db.ListFolders() {
|
||||||
|
folder := []byte(folderStr)
|
||||||
|
db.withHave(folder, protocol.LocalDeviceID[:], nil, false, func(f FileIntf) bool {
|
||||||
|
if !f.IsInvalid() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
fi := f.(protocol.FileInfo)
|
||||||
|
fi.RawInvalid = false
|
||||||
|
fi.LocalFlags = protocol.FlagLocalIgnored
|
||||||
|
bs, _ := fi.Marshal()
|
||||||
|
|
||||||
|
dk = db.deviceKeyInto(dk, folder, protocol.LocalDeviceID[:], []byte(fi.Name))
|
||||||
|
t.Put(dk, bs)
|
||||||
|
|
||||||
|
t.checkFlush()
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -154,7 +154,7 @@ func TestDropIndexIDs(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInvalidFiles(t *testing.T) {
|
func TestIgnoredFiles(t *testing.T) {
|
||||||
ldb, err := openJSONS("testdata/v0.14.48-ignoredfiles.db.jsons")
|
ldb, err := openJSONS("testdata/v0.14.48-ignoredfiles.db.jsons")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -192,27 +192,42 @@ func TestInvalidFiles(t *testing.T) {
|
||||||
// },
|
// },
|
||||||
// })
|
// })
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
|
||||||
fi, ok := fs.Get(protocol.LocalDeviceID, "foo")
|
fi, ok := fs.Get(protocol.LocalDeviceID, "foo")
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("foo should exist")
|
t.Fatal("foo should exist")
|
||||||
}
|
}
|
||||||
if !fi.Invalid {
|
if !fi.IsInvalid() {
|
||||||
t.Error("foo should be invalid")
|
t.Error("foo should be invalid")
|
||||||
}
|
}
|
||||||
|
if !fi.IsIgnored() {
|
||||||
|
t.Error("foo should be ignored")
|
||||||
|
}
|
||||||
|
|
||||||
fi, ok = fs.Get(protocol.LocalDeviceID, "bar")
|
fi, ok = fs.Get(protocol.LocalDeviceID, "bar")
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("bar should exist")
|
t.Fatal("bar should exist")
|
||||||
}
|
}
|
||||||
if fi.Invalid {
|
if fi.IsInvalid() {
|
||||||
t.Error("bar should not be invalid")
|
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 = fs.Get(protocol.DeviceID{42}, "baz")
|
fi, ok = fs.Get(protocol.DeviceID{42}, "baz")
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("baz should exist")
|
t.Fatal("baz should exist")
|
||||||
}
|
}
|
||||||
if !fi.Invalid {
|
if !fi.IsInvalid() {
|
||||||
|
t.Error("baz should be invalid")
|
||||||
|
}
|
||||||
|
if !fi.IsInvalid() {
|
||||||
t.Error("baz should be invalid")
|
t.Error("baz should be invalid")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,7 +235,10 @@ func TestInvalidFiles(t *testing.T) {
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("quux should exist")
|
t.Fatal("quux should exist")
|
||||||
}
|
}
|
||||||
if fi.Invalid {
|
if fi.IsInvalid() {
|
||||||
|
t.Error("quux should not be invalid")
|
||||||
|
}
|
||||||
|
if fi.IsInvalid() {
|
||||||
t.Error("quux should not be invalid")
|
t.Error("quux should not be invalid")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -245,13 +263,13 @@ func init() {
|
||||||
},
|
},
|
||||||
remoteDevice0: {
|
remoteDevice0: {
|
||||||
protocol.FileInfo{Name: "b", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1001}}}, Blocks: genBlocks(2)},
|
protocol.FileInfo{Name: "b", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1001}}}, Blocks: genBlocks(2)},
|
||||||
protocol.FileInfo{Name: "c", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1002}}}, Blocks: genBlocks(5), Invalid: true},
|
protocol.FileInfo{Name: "c", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1002}}}, Blocks: genBlocks(5), RawInvalid: true},
|
||||||
protocol.FileInfo{Name: "d", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1003}}}, Blocks: genBlocks(7)},
|
protocol.FileInfo{Name: "d", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1003}}}, Blocks: genBlocks(7)},
|
||||||
},
|
},
|
||||||
remoteDevice1: {
|
remoteDevice1: {
|
||||||
protocol.FileInfo{Name: "c", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1002}}}, Blocks: genBlocks(7)},
|
protocol.FileInfo{Name: "c", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1002}}}, Blocks: genBlocks(7)},
|
||||||
protocol.FileInfo{Name: "d", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1003}}}, Blocks: genBlocks(5), Invalid: true},
|
protocol.FileInfo{Name: "d", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1003}}}, Blocks: genBlocks(5), RawInvalid: true},
|
||||||
protocol.FileInfo{Name: invalid, Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1004}}}, Blocks: genBlocks(5), Invalid: true},
|
protocol.FileInfo{Name: invalid, Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1004}}}, Blocks: genBlocks(5), RawInvalid: true},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,7 +85,7 @@ func (t readWriteTransaction) insertFile(fk, folder, device []byte, file protoco
|
||||||
// file. If the device is already present in the list, the version is updated.
|
// file. If the device is already present in the list, the version is updated.
|
||||||
// If the file does not have an entry in the global list, it is created.
|
// If the file does not have an entry in the global list, it is created.
|
||||||
func (t readWriteTransaction) updateGlobal(gk, folder, device []byte, file protocol.FileInfo, meta *metadataTracker) bool {
|
func (t readWriteTransaction) updateGlobal(gk, folder, device []byte, file protocol.FileInfo, meta *metadataTracker) bool {
|
||||||
l.Debugf("update global; folder=%q device=%v file=%q version=%v invalid=%v", folder, protocol.DeviceIDFromBytes(device), file.Name, file.Version, file.Invalid)
|
l.Debugf("update global; folder=%q device=%v file=%q version=%v invalid=%v", folder, protocol.DeviceIDFromBytes(device), file.Name, file.Version, file.IsInvalid())
|
||||||
|
|
||||||
var fl VersionList
|
var fl VersionList
|
||||||
if svl, err := t.Get(gk, nil); err == nil {
|
if svl, err := t.Get(gk, nil); err == nil {
|
||||||
|
|
|
@ -147,7 +147,7 @@ func (s *FileSet) Update(device protocol.DeviceID, fs []protocol.FileInfo) {
|
||||||
for _, nf := range oldFs {
|
for _, nf := range oldFs {
|
||||||
dk = s.db.deviceKeyInto(dk, folder, device[:], []byte(osutil.NormalizedFilename(nf.Name)))
|
dk = s.db.deviceKeyInto(dk, folder, device[:], []byte(osutil.NormalizedFilename(nf.Name)))
|
||||||
ef, ok := s.db.getFile(dk)
|
ef, ok := s.db.getFile(dk)
|
||||||
if ok && ef.Version.Equal(nf.Version) && ef.Invalid == nf.Invalid {
|
if ok && ef.Version.Equal(nf.Version) && ef.IsInvalid() == nf.IsInvalid() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -117,7 +117,7 @@ func (l fileList) String() string {
|
||||||
func TestGlobalSet(t *testing.T) {
|
func TestGlobalSet(t *testing.T) {
|
||||||
ldb := db.OpenMemory()
|
ldb := db.OpenMemory()
|
||||||
|
|
||||||
m := db.NewFileSet("test)", fs.NewFilesystem(fs.FilesystemTypeBasic, "."), ldb)
|
m := db.NewFileSet("test", fs.NewFilesystem(fs.FilesystemTypeBasic, "."), ldb)
|
||||||
|
|
||||||
local0 := fileList{
|
local0 := fileList{
|
||||||
protocol.FileInfo{Name: "a", Sequence: 1, Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}, Blocks: genBlocks(1)},
|
protocol.FileInfo{Name: "a", Sequence: 1, Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}, Blocks: genBlocks(1)},
|
||||||
|
@ -332,20 +332,20 @@ func TestGlobalSet(t *testing.T) {
|
||||||
func TestNeedWithInvalid(t *testing.T) {
|
func TestNeedWithInvalid(t *testing.T) {
|
||||||
ldb := db.OpenMemory()
|
ldb := db.OpenMemory()
|
||||||
|
|
||||||
s := db.NewFileSet("test)", fs.NewFilesystem(fs.FilesystemTypeBasic, "."), ldb)
|
s := db.NewFileSet("test", fs.NewFilesystem(fs.FilesystemTypeBasic, "."), ldb)
|
||||||
|
|
||||||
localHave := fileList{
|
localHave := fileList{
|
||||||
protocol.FileInfo{Name: "a", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}, Blocks: genBlocks(1)},
|
protocol.FileInfo{Name: "a", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}, Blocks: genBlocks(1)},
|
||||||
}
|
}
|
||||||
remote0Have := fileList{
|
remote0Have := fileList{
|
||||||
protocol.FileInfo{Name: "b", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1001}}}, Blocks: genBlocks(2)},
|
protocol.FileInfo{Name: "b", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1001}}}, Blocks: genBlocks(2)},
|
||||||
protocol.FileInfo{Name: "c", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1002}}}, Blocks: genBlocks(5), Invalid: true},
|
protocol.FileInfo{Name: "c", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1002}}}, Blocks: genBlocks(5), RawInvalid: true},
|
||||||
protocol.FileInfo{Name: "d", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1003}}}, Blocks: genBlocks(7)},
|
protocol.FileInfo{Name: "d", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1003}}}, Blocks: genBlocks(7)},
|
||||||
}
|
}
|
||||||
remote1Have := fileList{
|
remote1Have := fileList{
|
||||||
protocol.FileInfo{Name: "c", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1002}}}, Blocks: genBlocks(7)},
|
protocol.FileInfo{Name: "c", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1002}}}, Blocks: genBlocks(7)},
|
||||||
protocol.FileInfo{Name: "d", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1003}}}, Blocks: genBlocks(5), Invalid: true},
|
protocol.FileInfo{Name: "d", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1003}}}, Blocks: genBlocks(5), RawInvalid: true},
|
||||||
protocol.FileInfo{Name: "e", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1004}}}, Blocks: genBlocks(5), Invalid: true},
|
protocol.FileInfo{Name: "e", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1004}}}, Blocks: genBlocks(5), RawInvalid: true},
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedNeed := fileList{
|
expectedNeed := fileList{
|
||||||
|
@ -369,16 +369,16 @@ func TestNeedWithInvalid(t *testing.T) {
|
||||||
func TestUpdateToInvalid(t *testing.T) {
|
func TestUpdateToInvalid(t *testing.T) {
|
||||||
ldb := db.OpenMemory()
|
ldb := db.OpenMemory()
|
||||||
|
|
||||||
folder := "test)"
|
folder := "test"
|
||||||
s := db.NewFileSet(folder, fs.NewFilesystem(fs.FilesystemTypeBasic, "."), ldb)
|
s := db.NewFileSet(folder, fs.NewFilesystem(fs.FilesystemTypeBasic, "."), ldb)
|
||||||
f := db.NewBlockFinder(ldb)
|
f := db.NewBlockFinder(ldb)
|
||||||
|
|
||||||
localHave := fileList{
|
localHave := fileList{
|
||||||
protocol.FileInfo{Name: "a", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}, Blocks: genBlocks(1)},
|
protocol.FileInfo{Name: "a", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}, Blocks: genBlocks(1)},
|
||||||
protocol.FileInfo{Name: "b", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1001}}}, Blocks: genBlocks(2)},
|
protocol.FileInfo{Name: "b", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1001}}}, Blocks: genBlocks(2)},
|
||||||
protocol.FileInfo{Name: "c", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1002}}}, Blocks: genBlocks(5), Invalid: true},
|
protocol.FileInfo{Name: "c", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1002}}}, Blocks: genBlocks(5), LocalFlags: protocol.FlagLocalIgnored},
|
||||||
protocol.FileInfo{Name: "d", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1003}}}, Blocks: genBlocks(7)},
|
protocol.FileInfo{Name: "d", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1003}}}, Blocks: genBlocks(7)},
|
||||||
protocol.FileInfo{Name: "e", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1003}}}, Invalid: true},
|
protocol.FileInfo{Name: "e", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1003}}}, LocalFlags: protocol.FlagLocalIgnored},
|
||||||
}
|
}
|
||||||
|
|
||||||
replace(s, protocol.LocalDeviceID, localHave)
|
replace(s, protocol.LocalDeviceID, localHave)
|
||||||
|
@ -391,10 +391,13 @@ func TestUpdateToInvalid(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
oldBlockHash := localHave[1].Blocks[0].Hash
|
oldBlockHash := localHave[1].Blocks[0].Hash
|
||||||
localHave[1].Invalid = true
|
|
||||||
|
localHave[1].LocalFlags = protocol.FlagLocalIgnored
|
||||||
localHave[1].Blocks = nil
|
localHave[1].Blocks = nil
|
||||||
localHave[4].Invalid = false
|
|
||||||
|
localHave[4].LocalFlags = 0
|
||||||
localHave[4].Blocks = genBlocks(3)
|
localHave[4].Blocks = genBlocks(3)
|
||||||
|
|
||||||
s.Update(protocol.LocalDeviceID, append(fileList{}, localHave[1], localHave[4]))
|
s.Update(protocol.LocalDeviceID, append(fileList{}, localHave[1], localHave[4]))
|
||||||
|
|
||||||
have = fileList(haveList(s, protocol.LocalDeviceID))
|
have = fileList(haveList(s, protocol.LocalDeviceID))
|
||||||
|
@ -425,19 +428,19 @@ func TestUpdateToInvalid(t *testing.T) {
|
||||||
func TestInvalidAvailability(t *testing.T) {
|
func TestInvalidAvailability(t *testing.T) {
|
||||||
ldb := db.OpenMemory()
|
ldb := db.OpenMemory()
|
||||||
|
|
||||||
s := db.NewFileSet("test)", fs.NewFilesystem(fs.FilesystemTypeBasic, "."), ldb)
|
s := db.NewFileSet("test", fs.NewFilesystem(fs.FilesystemTypeBasic, "."), ldb)
|
||||||
|
|
||||||
remote0Have := fileList{
|
remote0Have := fileList{
|
||||||
protocol.FileInfo{Name: "both", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1001}}}, Blocks: genBlocks(2)},
|
protocol.FileInfo{Name: "both", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1001}}}, Blocks: genBlocks(2)},
|
||||||
protocol.FileInfo{Name: "r1only", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1002}}}, Blocks: genBlocks(5), Invalid: true},
|
protocol.FileInfo{Name: "r1only", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1002}}}, Blocks: genBlocks(5), RawInvalid: true},
|
||||||
protocol.FileInfo{Name: "r0only", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1003}}}, Blocks: genBlocks(7)},
|
protocol.FileInfo{Name: "r0only", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1003}}}, Blocks: genBlocks(7)},
|
||||||
protocol.FileInfo{Name: "none", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1004}}}, Blocks: genBlocks(5), Invalid: true},
|
protocol.FileInfo{Name: "none", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1004}}}, Blocks: genBlocks(5), RawInvalid: true},
|
||||||
}
|
}
|
||||||
remote1Have := fileList{
|
remote1Have := fileList{
|
||||||
protocol.FileInfo{Name: "both", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1001}}}, Blocks: genBlocks(2)},
|
protocol.FileInfo{Name: "both", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1001}}}, Blocks: genBlocks(2)},
|
||||||
protocol.FileInfo{Name: "r1only", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1002}}}, Blocks: genBlocks(7)},
|
protocol.FileInfo{Name: "r1only", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1002}}}, Blocks: genBlocks(7)},
|
||||||
protocol.FileInfo{Name: "r0only", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1003}}}, Blocks: genBlocks(5), Invalid: true},
|
protocol.FileInfo{Name: "r0only", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1003}}}, Blocks: genBlocks(5), RawInvalid: true},
|
||||||
protocol.FileInfo{Name: "none", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1004}}}, Blocks: genBlocks(5), Invalid: true},
|
protocol.FileInfo{Name: "none", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1004}}}, Blocks: genBlocks(5), RawInvalid: true},
|
||||||
}
|
}
|
||||||
|
|
||||||
replace(s, remoteDevice0, remote0Have)
|
replace(s, remoteDevice0, remote0Have)
|
||||||
|
@ -463,7 +466,7 @@ func TestInvalidAvailability(t *testing.T) {
|
||||||
func TestGlobalReset(t *testing.T) {
|
func TestGlobalReset(t *testing.T) {
|
||||||
ldb := db.OpenMemory()
|
ldb := db.OpenMemory()
|
||||||
|
|
||||||
m := db.NewFileSet("test)", fs.NewFilesystem(fs.FilesystemTypeBasic, "."), ldb)
|
m := db.NewFileSet("test", fs.NewFilesystem(fs.FilesystemTypeBasic, "."), ldb)
|
||||||
|
|
||||||
local := []protocol.FileInfo{
|
local := []protocol.FileInfo{
|
||||||
{Name: "a", Sequence: 1, Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}},
|
{Name: "a", Sequence: 1, Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}},
|
||||||
|
@ -501,7 +504,7 @@ func TestGlobalReset(t *testing.T) {
|
||||||
func TestNeed(t *testing.T) {
|
func TestNeed(t *testing.T) {
|
||||||
ldb := db.OpenMemory()
|
ldb := db.OpenMemory()
|
||||||
|
|
||||||
m := db.NewFileSet("test)", fs.NewFilesystem(fs.FilesystemTypeBasic, "."), ldb)
|
m := db.NewFileSet("test", fs.NewFilesystem(fs.FilesystemTypeBasic, "."), ldb)
|
||||||
|
|
||||||
local := []protocol.FileInfo{
|
local := []protocol.FileInfo{
|
||||||
{Name: "b", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}},
|
{Name: "b", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}},
|
||||||
|
@ -539,7 +542,7 @@ func TestNeed(t *testing.T) {
|
||||||
func TestSequence(t *testing.T) {
|
func TestSequence(t *testing.T) {
|
||||||
ldb := db.OpenMemory()
|
ldb := db.OpenMemory()
|
||||||
|
|
||||||
m := db.NewFileSet("test)", fs.NewFilesystem(fs.FilesystemTypeBasic, "."), ldb)
|
m := db.NewFileSet("test", fs.NewFilesystem(fs.FilesystemTypeBasic, "."), ldb)
|
||||||
|
|
||||||
local1 := []protocol.FileInfo{
|
local1 := []protocol.FileInfo{
|
||||||
{Name: "a", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}},
|
{Name: "a", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}},
|
||||||
|
@ -623,7 +626,7 @@ func TestGlobalNeedWithInvalid(t *testing.T) {
|
||||||
|
|
||||||
rem0 := fileList{
|
rem0 := fileList{
|
||||||
protocol.FileInfo{Name: "a", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1002}}}, Blocks: genBlocks(4)},
|
protocol.FileInfo{Name: "a", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1002}}}, Blocks: genBlocks(4)},
|
||||||
protocol.FileInfo{Name: "b", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1002}}}, Invalid: true},
|
protocol.FileInfo{Name: "b", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1002}}}, RawInvalid: true},
|
||||||
protocol.FileInfo{Name: "c", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1002}}}, Blocks: genBlocks(4)},
|
protocol.FileInfo{Name: "c", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1002}}}, Blocks: genBlocks(4)},
|
||||||
protocol.FileInfo{Name: "d", Version: protocol.Vector{Counters: []protocol.Counter{{ID: remoteDevice0.Short(), Value: 1002}}}},
|
protocol.FileInfo{Name: "d", Version: protocol.Vector{Counters: []protocol.Counter{{ID: remoteDevice0.Short(), Value: 1002}}}},
|
||||||
}
|
}
|
||||||
|
@ -632,8 +635,8 @@ func TestGlobalNeedWithInvalid(t *testing.T) {
|
||||||
rem1 := fileList{
|
rem1 := fileList{
|
||||||
protocol.FileInfo{Name: "a", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1002}}}, Blocks: genBlocks(4)},
|
protocol.FileInfo{Name: "a", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1002}}}, Blocks: genBlocks(4)},
|
||||||
protocol.FileInfo{Name: "b", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1002}}}, Blocks: genBlocks(4)},
|
protocol.FileInfo{Name: "b", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1002}}}, Blocks: genBlocks(4)},
|
||||||
protocol.FileInfo{Name: "c", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1002}}}, Invalid: true},
|
protocol.FileInfo{Name: "c", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1002}}}, RawInvalid: true},
|
||||||
protocol.FileInfo{Name: "d", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1002}}}, Invalid: true, ModifiedS: 10},
|
protocol.FileInfo{Name: "d", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1002}}}, RawInvalid: true, ModifiedS: 10},
|
||||||
}
|
}
|
||||||
replace(s, remoteDevice1, rem1)
|
replace(s, remoteDevice1, rem1)
|
||||||
|
|
||||||
|
@ -690,7 +693,7 @@ func TestCommitted(t *testing.T) {
|
||||||
|
|
||||||
ldb := db.OpenMemory()
|
ldb := db.OpenMemory()
|
||||||
|
|
||||||
s := db.NewFileSet("test)", fs.NewFilesystem(fs.FilesystemTypeBasic, "."), ldb)
|
s := db.NewFileSet("test", fs.NewFilesystem(fs.FilesystemTypeBasic, "."), ldb)
|
||||||
|
|
||||||
local := []protocol.FileInfo{
|
local := []protocol.FileInfo{
|
||||||
{Name: string("file"), Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}},
|
{Name: string("file"), Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}},
|
||||||
|
@ -736,7 +739,7 @@ func BenchmarkUpdateOneFile(b *testing.B) {
|
||||||
os.RemoveAll("testdata/benchmarkupdate.db")
|
os.RemoveAll("testdata/benchmarkupdate.db")
|
||||||
}()
|
}()
|
||||||
|
|
||||||
m := db.NewFileSet("test)", fs.NewFilesystem(fs.FilesystemTypeBasic, "."), ldb)
|
m := db.NewFileSet("test", fs.NewFilesystem(fs.FilesystemTypeBasic, "."), ldb)
|
||||||
replace(m, protocol.LocalDeviceID, local0)
|
replace(m, protocol.LocalDeviceID, local0)
|
||||||
l := local0[4:5]
|
l := local0[4:5]
|
||||||
|
|
||||||
|
@ -751,7 +754,7 @@ func BenchmarkUpdateOneFile(b *testing.B) {
|
||||||
func TestIndexID(t *testing.T) {
|
func TestIndexID(t *testing.T) {
|
||||||
ldb := db.OpenMemory()
|
ldb := db.OpenMemory()
|
||||||
|
|
||||||
s := db.NewFileSet("test)", fs.NewFilesystem(fs.FilesystemTypeBasic, "."), ldb)
|
s := db.NewFileSet("test", fs.NewFilesystem(fs.FilesystemTypeBasic, "."), ldb)
|
||||||
|
|
||||||
// The Index ID for some random device is zero by default.
|
// The Index ID for some random device is zero by default.
|
||||||
id := s.IndexID(remoteDevice0)
|
id := s.IndexID(remoteDevice0)
|
||||||
|
@ -783,7 +786,7 @@ func TestIndexID(t *testing.T) {
|
||||||
func TestDropFiles(t *testing.T) {
|
func TestDropFiles(t *testing.T) {
|
||||||
ldb := db.OpenMemory()
|
ldb := db.OpenMemory()
|
||||||
|
|
||||||
m := db.NewFileSet("test)", fs.NewFilesystem(fs.FilesystemTypeBasic, "."), ldb)
|
m := db.NewFileSet("test", fs.NewFilesystem(fs.FilesystemTypeBasic, "."), ldb)
|
||||||
|
|
||||||
local0 := fileList{
|
local0 := fileList{
|
||||||
protocol.FileInfo{Name: "a", Sequence: 1, Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}, Blocks: genBlocks(1)},
|
protocol.FileInfo{Name: "a", Sequence: 1, Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}, Blocks: genBlocks(1)},
|
||||||
|
@ -846,11 +849,11 @@ func TestDropFiles(t *testing.T) {
|
||||||
func TestIssue4701(t *testing.T) {
|
func TestIssue4701(t *testing.T) {
|
||||||
ldb := db.OpenMemory()
|
ldb := db.OpenMemory()
|
||||||
|
|
||||||
s := db.NewFileSet("test)", fs.NewFilesystem(fs.FilesystemTypeBasic, "."), ldb)
|
s := db.NewFileSet("test", fs.NewFilesystem(fs.FilesystemTypeBasic, "."), ldb)
|
||||||
|
|
||||||
localHave := fileList{
|
localHave := fileList{
|
||||||
protocol.FileInfo{Name: "a", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}},
|
protocol.FileInfo{Name: "a", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}},
|
||||||
protocol.FileInfo{Name: "b", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}, Invalid: true},
|
protocol.FileInfo{Name: "b", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}, LocalFlags: protocol.FlagLocalIgnored},
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Update(protocol.LocalDeviceID, localHave)
|
s.Update(protocol.LocalDeviceID, localHave)
|
||||||
|
@ -862,7 +865,7 @@ func TestIssue4701(t *testing.T) {
|
||||||
t.Errorf("Expected 1 global file, got %v", c.Files)
|
t.Errorf("Expected 1 global file, got %v", c.Files)
|
||||||
}
|
}
|
||||||
|
|
||||||
localHave[1].Invalid = false
|
localHave[1].LocalFlags = 0
|
||||||
s.Update(protocol.LocalDeviceID, localHave)
|
s.Update(protocol.LocalDeviceID, localHave)
|
||||||
|
|
||||||
if c := s.LocalSize(); c.Files != 2 {
|
if c := s.LocalSize(); c.Files != 2 {
|
||||||
|
@ -872,8 +875,8 @@ func TestIssue4701(t *testing.T) {
|
||||||
t.Errorf("Expected 2 global files, got %v", c.Files)
|
t.Errorf("Expected 2 global files, got %v", c.Files)
|
||||||
}
|
}
|
||||||
|
|
||||||
localHave[0].Invalid = true
|
localHave[0].LocalFlags = protocol.FlagLocalIgnored
|
||||||
localHave[1].Invalid = true
|
localHave[1].LocalFlags = protocol.FlagLocalIgnored
|
||||||
s.Update(protocol.LocalDeviceID, localHave)
|
s.Update(protocol.LocalDeviceID, localHave)
|
||||||
|
|
||||||
if c := s.LocalSize(); c.Files != 0 {
|
if c := s.LocalSize(); c.Files != 0 {
|
||||||
|
@ -887,16 +890,16 @@ func TestIssue4701(t *testing.T) {
|
||||||
func TestWithHaveSequence(t *testing.T) {
|
func TestWithHaveSequence(t *testing.T) {
|
||||||
ldb := db.OpenMemory()
|
ldb := db.OpenMemory()
|
||||||
|
|
||||||
folder := "test)"
|
folder := "test"
|
||||||
s := db.NewFileSet(folder, fs.NewFilesystem(fs.FilesystemTypeBasic, "."), ldb)
|
s := db.NewFileSet(folder, fs.NewFilesystem(fs.FilesystemTypeBasic, "."), ldb)
|
||||||
|
|
||||||
// The files must not be in alphabetical order
|
// The files must not be in alphabetical order
|
||||||
localHave := fileList{
|
localHave := fileList{
|
||||||
protocol.FileInfo{Name: "e", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1003}}}, Invalid: true},
|
protocol.FileInfo{Name: "e", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1003}}}, RawInvalid: true},
|
||||||
protocol.FileInfo{Name: "b", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1001}}}, Blocks: genBlocks(2)},
|
protocol.FileInfo{Name: "b", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1001}}}, Blocks: genBlocks(2)},
|
||||||
protocol.FileInfo{Name: "d", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1003}}}, Blocks: genBlocks(7)},
|
protocol.FileInfo{Name: "d", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1003}}}, Blocks: genBlocks(7)},
|
||||||
protocol.FileInfo{Name: "a", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}, Blocks: genBlocks(1)},
|
protocol.FileInfo{Name: "a", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}, Blocks: genBlocks(1)},
|
||||||
protocol.FileInfo{Name: "c", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1002}}}, Blocks: genBlocks(5), Invalid: true},
|
protocol.FileInfo{Name: "c", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1002}}}, Blocks: genBlocks(5), RawInvalid: true},
|
||||||
}
|
}
|
||||||
|
|
||||||
replace(s, protocol.LocalDeviceID, localHave)
|
replace(s, protocol.LocalDeviceID, localHave)
|
||||||
|
@ -1018,7 +1021,7 @@ func TestIssue5007(t *testing.T) {
|
||||||
t.Fatalf("Local need incorrect;\n A: %v !=\n E: %v", need[0], fs[0])
|
t.Fatalf("Local need incorrect;\n A: %v !=\n E: %v", need[0], fs[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
fs[0].Invalid = true
|
fs[0].LocalFlags = protocol.FlagLocalIgnored
|
||||||
s.Update(protocol.LocalDeviceID, fs)
|
s.Update(protocol.LocalDeviceID, fs)
|
||||||
|
|
||||||
if need := needList(s, protocol.LocalDeviceID); len(need) != 0 {
|
if need := needList(s, protocol.LocalDeviceID); len(need) != 0 {
|
||||||
|
|
|
@ -17,8 +17,19 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func (f FileInfoTruncated) String() string {
|
func (f FileInfoTruncated) String() string {
|
||||||
return fmt.Sprintf("File{Name:%q, Permissions:0%o, Modified:%v, Version:%v, Length:%d, Deleted:%v, Invalid:%v, NoPermissions:%v, BlockSize:%d}",
|
switch f.Type {
|
||||||
f.Name, f.Permissions, f.ModTime(), f.Version, f.Size, f.Deleted, f.Invalid, f.NoPermissions, f.RawBlockSize)
|
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.FileInfoTypeDeprecatedSymlinkDirectory, protocol.FileInfoTypeDeprecatedSymlinkFile:
|
||||||
|
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")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f FileInfoTruncated) IsDeleted() bool {
|
func (f FileInfoTruncated) IsDeleted() bool {
|
||||||
|
@ -26,7 +37,15 @@ func (f FileInfoTruncated) IsDeleted() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f FileInfoTruncated) IsInvalid() bool {
|
func (f FileInfoTruncated) IsInvalid() bool {
|
||||||
return f.Invalid
|
return f.RawInvalid || f.LocalFlags&protocol.LocalInvalidFlags != 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) IsDirectory() bool {
|
func (f FileInfoTruncated) IsDirectory() bool {
|
||||||
|
@ -79,15 +98,15 @@ func (f FileInfoTruncated) FileVersion() protocol.Vector {
|
||||||
return f.Version
|
return f.Version
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f FileInfoTruncated) ConvertToInvalidFileInfo(invalidatedBy protocol.ShortID) protocol.FileInfo {
|
func (f FileInfoTruncated) ConvertToIgnoredFileInfo(by protocol.ShortID) protocol.FileInfo {
|
||||||
return protocol.FileInfo{
|
return protocol.FileInfo{
|
||||||
Name: f.Name,
|
Name: f.Name,
|
||||||
Type: f.Type,
|
Type: f.Type,
|
||||||
ModifiedS: f.ModifiedS,
|
ModifiedS: f.ModifiedS,
|
||||||
ModifiedNs: f.ModifiedNs,
|
ModifiedNs: f.ModifiedNs,
|
||||||
ModifiedBy: invalidatedBy,
|
ModifiedBy: by,
|
||||||
Invalid: true,
|
|
||||||
Version: f.Version,
|
Version: f.Version,
|
||||||
RawBlockSize: f.RawBlockSize,
|
RawBlockSize: f.RawBlockSize,
|
||||||
|
LocalFlags: protocol.FlagLocalIgnored,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,13 +66,15 @@ type FileInfoTruncated struct {
|
||||||
ModifiedNs int32 `protobuf:"varint,11,opt,name=modified_ns,json=modifiedNs,proto3" json:"modified_ns,omitempty"`
|
ModifiedNs int32 `protobuf:"varint,11,opt,name=modified_ns,json=modifiedNs,proto3" json:"modified_ns,omitempty"`
|
||||||
ModifiedBy github_com_syncthing_syncthing_lib_protocol.ShortID `protobuf:"varint,12,opt,name=modified_by,json=modifiedBy,proto3,customtype=github.com/syncthing/syncthing/lib/protocol.ShortID" json:"modified_by"`
|
ModifiedBy github_com_syncthing_syncthing_lib_protocol.ShortID `protobuf:"varint,12,opt,name=modified_by,json=modifiedBy,proto3,customtype=github.com/syncthing/syncthing/lib/protocol.ShortID" json:"modified_by"`
|
||||||
Deleted bool `protobuf:"varint,6,opt,name=deleted,proto3" json:"deleted,omitempty"`
|
Deleted bool `protobuf:"varint,6,opt,name=deleted,proto3" json:"deleted,omitempty"`
|
||||||
Invalid bool `protobuf:"varint,7,opt,name=invalid,proto3" json:"invalid,omitempty"`
|
RawInvalid bool `protobuf:"varint,7,opt,name=invalid,proto3" json:"invalid,omitempty"`
|
||||||
NoPermissions bool `protobuf:"varint,8,opt,name=no_permissions,json=noPermissions,proto3" json:"no_permissions,omitempty"`
|
NoPermissions bool `protobuf:"varint,8,opt,name=no_permissions,json=noPermissions,proto3" json:"no_permissions,omitempty"`
|
||||||
Version protocol.Vector `protobuf:"bytes,9,opt,name=version" json:"version"`
|
Version protocol.Vector `protobuf:"bytes,9,opt,name=version" json:"version"`
|
||||||
Sequence int64 `protobuf:"varint,10,opt,name=sequence,proto3" json:"sequence,omitempty"`
|
Sequence int64 `protobuf:"varint,10,opt,name=sequence,proto3" json:"sequence,omitempty"`
|
||||||
RawBlockSize int32 `protobuf:"varint,13,opt,name=block_size,json=blockSize,proto3" json:"block_size,omitempty"`
|
RawBlockSize int32 `protobuf:"varint,13,opt,name=block_size,json=blockSize,proto3" json:"block_size,omitempty"`
|
||||||
// repeated BlockInfo Blocks = 16
|
// repeated BlockInfo Blocks = 16
|
||||||
SymlinkTarget string `protobuf:"bytes,17,opt,name=symlink_target,json=symlinkTarget,proto3" json:"symlink_target,omitempty"`
|
SymlinkTarget string `protobuf:"bytes,17,opt,name=symlink_target,json=symlinkTarget,proto3" json:"symlink_target,omitempty"`
|
||||||
|
// see bep.proto
|
||||||
|
LocalFlags uint32 `protobuf:"varint,1000,opt,name=local_flags,json=localFlags,proto3" json:"local_flags,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *FileInfoTruncated) Reset() { *m = FileInfoTruncated{} }
|
func (m *FileInfoTruncated) Reset() { *m = FileInfoTruncated{} }
|
||||||
|
@ -236,10 +238,10 @@ func (m *FileInfoTruncated) MarshalTo(dAtA []byte) (int, error) {
|
||||||
}
|
}
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
if m.Invalid {
|
if m.RawInvalid {
|
||||||
dAtA[i] = 0x38
|
dAtA[i] = 0x38
|
||||||
i++
|
i++
|
||||||
if m.Invalid {
|
if m.RawInvalid {
|
||||||
dAtA[i] = 1
|
dAtA[i] = 1
|
||||||
} else {
|
} else {
|
||||||
dAtA[i] = 0
|
dAtA[i] = 0
|
||||||
|
@ -292,6 +294,13 @@ func (m *FileInfoTruncated) MarshalTo(dAtA []byte) (int, error) {
|
||||||
i = encodeVarintStructs(dAtA, i, uint64(len(m.SymlinkTarget)))
|
i = encodeVarintStructs(dAtA, i, uint64(len(m.SymlinkTarget)))
|
||||||
i += copy(dAtA[i:], m.SymlinkTarget)
|
i += copy(dAtA[i:], m.SymlinkTarget)
|
||||||
}
|
}
|
||||||
|
if m.LocalFlags != 0 {
|
||||||
|
dAtA[i] = 0xc0
|
||||||
|
i++
|
||||||
|
dAtA[i] = 0x3e
|
||||||
|
i++
|
||||||
|
i = encodeVarintStructs(dAtA, i, uint64(m.LocalFlags))
|
||||||
|
}
|
||||||
return i, nil
|
return i, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -462,7 +471,7 @@ func (m *FileInfoTruncated) ProtoSize() (n int) {
|
||||||
if m.Deleted {
|
if m.Deleted {
|
||||||
n += 2
|
n += 2
|
||||||
}
|
}
|
||||||
if m.Invalid {
|
if m.RawInvalid {
|
||||||
n += 2
|
n += 2
|
||||||
}
|
}
|
||||||
if m.NoPermissions {
|
if m.NoPermissions {
|
||||||
|
@ -486,6 +495,9 @@ func (m *FileInfoTruncated) ProtoSize() (n int) {
|
||||||
if l > 0 {
|
if l > 0 {
|
||||||
n += 2 + l + sovStructs(uint64(l))
|
n += 2 + l + sovStructs(uint64(l))
|
||||||
}
|
}
|
||||||
|
if m.LocalFlags != 0 {
|
||||||
|
n += 2 + sovStructs(uint64(m.LocalFlags))
|
||||||
|
}
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -913,7 +925,7 @@ func (m *FileInfoTruncated) Unmarshal(dAtA []byte) error {
|
||||||
m.Deleted = bool(v != 0)
|
m.Deleted = bool(v != 0)
|
||||||
case 7:
|
case 7:
|
||||||
if wireType != 0 {
|
if wireType != 0 {
|
||||||
return fmt.Errorf("proto: wrong wireType = %d for field Invalid", wireType)
|
return fmt.Errorf("proto: wrong wireType = %d for field RawInvalid", wireType)
|
||||||
}
|
}
|
||||||
var v int
|
var v int
|
||||||
for shift := uint(0); ; shift += 7 {
|
for shift := uint(0); ; shift += 7 {
|
||||||
|
@ -930,7 +942,7 @@ func (m *FileInfoTruncated) Unmarshal(dAtA []byte) error {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m.Invalid = bool(v != 0)
|
m.RawInvalid = bool(v != 0)
|
||||||
case 8:
|
case 8:
|
||||||
if wireType != 0 {
|
if wireType != 0 {
|
||||||
return fmt.Errorf("proto: wrong wireType = %d for field NoPermissions", wireType)
|
return fmt.Errorf("proto: wrong wireType = %d for field NoPermissions", wireType)
|
||||||
|
@ -1086,6 +1098,25 @@ func (m *FileInfoTruncated) Unmarshal(dAtA []byte) error {
|
||||||
}
|
}
|
||||||
m.SymlinkTarget = string(dAtA[iNdEx:postIndex])
|
m.SymlinkTarget = string(dAtA[iNdEx:postIndex])
|
||||||
iNdEx = postIndex
|
iNdEx = postIndex
|
||||||
|
case 1000:
|
||||||
|
if wireType != 0 {
|
||||||
|
return fmt.Errorf("proto: wrong wireType = %d for field LocalFlags", wireType)
|
||||||
|
}
|
||||||
|
m.LocalFlags = 0
|
||||||
|
for shift := uint(0); ; shift += 7 {
|
||||||
|
if shift >= 64 {
|
||||||
|
return ErrIntOverflowStructs
|
||||||
|
}
|
||||||
|
if iNdEx >= l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
b := dAtA[iNdEx]
|
||||||
|
iNdEx++
|
||||||
|
m.LocalFlags |= (uint32(b) & 0x7F) << shift
|
||||||
|
if b < 0x80 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
iNdEx = preIndex
|
iNdEx = preIndex
|
||||||
skippy, err := skipStructs(dAtA[iNdEx:])
|
skippy, err := skipStructs(dAtA[iNdEx:])
|
||||||
|
@ -1510,45 +1541,47 @@ var (
|
||||||
func init() { proto.RegisterFile("structs.proto", fileDescriptorStructs) }
|
func init() { proto.RegisterFile("structs.proto", fileDescriptorStructs) }
|
||||||
|
|
||||||
var fileDescriptorStructs = []byte{
|
var fileDescriptorStructs = []byte{
|
||||||
// 630 bytes of a gzipped FileDescriptorProto
|
// 663 bytes of a gzipped FileDescriptorProto
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x53, 0xcf, 0x6a, 0xdb, 0x4c,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x53, 0xcd, 0x6a, 0xdb, 0x40,
|
||||||
0x10, 0xb7, 0x62, 0xc9, 0xb1, 0x47, 0x76, 0xbe, 0x64, 0x09, 0x41, 0x18, 0x3e, 0x5b, 0x18, 0x0a,
|
0x10, 0xb6, 0x62, 0xf9, 0x6f, 0x6c, 0xa7, 0xc9, 0x12, 0x82, 0x30, 0xd4, 0x16, 0x86, 0x82, 0x28,
|
||||||
0xa2, 0x50, 0xb9, 0x4d, 0xe8, 0xa5, 0xbd, 0xb9, 0x21, 0x10, 0x28, 0x6d, 0x59, 0x87, 0x9c, 0x0a,
|
0xd4, 0x6e, 0x13, 0x7a, 0x69, 0x6f, 0x6a, 0x08, 0x18, 0x4a, 0x5b, 0xd6, 0x21, 0xa7, 0x82, 0xd1,
|
||||||
0xc6, 0x92, 0xd6, 0xce, 0x12, 0x79, 0xd7, 0xd1, 0xae, 0x52, 0x94, 0x27, 0xe9, 0x31, 0x4f, 0xd0,
|
0xcf, 0xda, 0x59, 0x22, 0x6b, 0x1d, 0xed, 0x3a, 0x41, 0x79, 0x92, 0x1e, 0xf3, 0x30, 0x3d, 0xe4,
|
||||||
0xa7, 0xe8, 0x21, 0xc7, 0x9e, 0x7b, 0x08, 0xad, 0xfb, 0x22, 0x45, 0xbb, 0x92, 0xa2, 0xf4, 0xd4,
|
0xd8, 0x73, 0x0f, 0x26, 0x75, 0x2f, 0x7d, 0x8c, 0xb2, 0xbb, 0x92, 0xa2, 0xf6, 0xd4, 0xde, 0xe6,
|
||||||
0xde, 0xe6, 0x37, 0xff, 0x67, 0x7e, 0x33, 0xd0, 0x13, 0x32, 0x49, 0x43, 0x29, 0xfc, 0x75, 0xc2,
|
0x9b, 0x9f, 0x9d, 0x6f, 0x66, 0xbe, 0x85, 0x2e, 0x17, 0xc9, 0x3a, 0x10, 0x7c, 0xb4, 0x4a, 0x98,
|
||||||
0x25, 0x47, 0x5b, 0x51, 0xd0, 0x7f, 0xb6, 0xa4, 0xf2, 0x22, 0x0d, 0xfc, 0x90, 0xaf, 0xc6, 0x4b,
|
0x60, 0x68, 0x27, 0xf4, 0x7b, 0x2f, 0x16, 0x54, 0x5c, 0xac, 0xfd, 0x51, 0xc0, 0x96, 0xe3, 0x05,
|
||||||
0xbe, 0xe4, 0x63, 0x65, 0x0a, 0xd2, 0x85, 0x42, 0x0a, 0x28, 0x49, 0x87, 0xf4, 0x5f, 0xd6, 0xdc,
|
0x5b, 0xb0, 0xb1, 0x0a, 0xf9, 0xeb, 0xb9, 0x42, 0x0a, 0x28, 0x4b, 0x97, 0xf4, 0x5e, 0x97, 0xd2,
|
||||||
0x45, 0xc6, 0x42, 0x79, 0x41, 0xd9, 0xb2, 0x26, 0xc5, 0x34, 0xd0, 0x19, 0x42, 0x1e, 0x8f, 0x03,
|
0x79, 0x1a, 0x07, 0xe2, 0x82, 0xc6, 0x8b, 0x92, 0x15, 0x51, 0x5f, 0xbf, 0x10, 0xb0, 0x68, 0xec,
|
||||||
0xb2, 0xd6, 0x61, 0xa3, 0x2b, 0xb0, 0x4f, 0x68, 0x4c, 0xce, 0x49, 0x22, 0x28, 0x67, 0xe8, 0x39,
|
0x93, 0x95, 0x2e, 0x1b, 0x5e, 0x41, 0xfb, 0x94, 0x46, 0xe4, 0x9c, 0x24, 0x9c, 0xb2, 0x18, 0xbd,
|
||||||
0x6c, 0x5f, 0x6b, 0xd1, 0x31, 0x5c, 0xc3, 0xb3, 0x0f, 0x77, 0xfd, 0x32, 0xc8, 0x3f, 0x27, 0xa1,
|
0x84, 0xc6, 0xb5, 0x36, 0x2d, 0xc3, 0x36, 0x9c, 0xf6, 0xd1, 0xde, 0x28, 0x2f, 0x1a, 0x9d, 0x93,
|
||||||
0xe4, 0xc9, 0xc4, 0xbc, 0xbb, 0x1f, 0x36, 0x70, 0xe9, 0x86, 0x0e, 0xa0, 0x15, 0x91, 0x6b, 0x1a,
|
0x40, 0xb0, 0xc4, 0x35, 0xef, 0x37, 0x83, 0x0a, 0xce, 0xd3, 0xd0, 0x21, 0xd4, 0x43, 0x72, 0x4d,
|
||||||
0x12, 0x67, 0xcb, 0x35, 0xbc, 0x2e, 0x2e, 0x10, 0x72, 0x60, 0x9b, 0xb2, 0xeb, 0x79, 0x4c, 0x23,
|
0x03, 0x62, 0xed, 0xd8, 0x86, 0xd3, 0xc1, 0x19, 0x42, 0x16, 0x34, 0x68, 0x7c, 0xed, 0x45, 0x34,
|
||||||
0xa7, 0xe9, 0x1a, 0x5e, 0x1b, 0x97, 0x70, 0x74, 0x02, 0x76, 0x51, 0xee, 0x2d, 0x15, 0x12, 0xbd,
|
0xb4, 0xaa, 0xb6, 0xe1, 0x34, 0x71, 0x0e, 0x87, 0xa7, 0xd0, 0xce, 0xda, 0xbd, 0xa7, 0x5c, 0xa0,
|
||||||
0x80, 0x76, 0x91, 0x4b, 0x38, 0x86, 0xdb, 0xf4, 0xec, 0xc3, 0xff, 0xfc, 0x28, 0xf0, 0x6b, 0x5d,
|
0x57, 0xd0, 0xcc, 0xde, 0xe2, 0x96, 0x61, 0x57, 0x9d, 0xf6, 0xd1, 0x93, 0x51, 0xe8, 0x8f, 0x4a,
|
||||||
0x15, 0x25, 0x2b, 0xb7, 0x57, 0xe6, 0xe7, 0xdb, 0x61, 0x63, 0xf4, 0xc5, 0x84, 0xbd, 0xdc, 0xeb,
|
0xac, 0xb2, 0x96, 0x45, 0xda, 0x1b, 0xf3, 0xcb, 0xdd, 0xa0, 0x32, 0x7c, 0x30, 0x61, 0x5f, 0x66,
|
||||||
0x94, 0x2d, 0xf8, 0x59, 0x92, 0xb2, 0x70, 0x2e, 0x49, 0x84, 0x10, 0x98, 0x6c, 0xbe, 0x22, 0xaa,
|
0x4d, 0xe2, 0x39, 0x3b, 0x4b, 0xd6, 0x71, 0xe0, 0x09, 0x12, 0x22, 0x04, 0x66, 0xec, 0x2d, 0x89,
|
||||||
0xfd, 0x0e, 0x56, 0x32, 0x7a, 0x0a, 0xa6, 0xcc, 0xd6, 0xba, 0xc3, 0x9d, 0xc3, 0x83, 0x87, 0x91,
|
0xa2, 0xdf, 0xc2, 0xca, 0x46, 0xcf, 0xc1, 0x14, 0xe9, 0x4a, 0x33, 0xdc, 0x3d, 0x3a, 0x7c, 0x1c,
|
||||||
0xaa, 0xf0, 0x6c, 0x4d, 0xb0, 0xf2, 0xc9, 0xe3, 0x05, 0xbd, 0x21, 0xaa, 0xe9, 0x26, 0x56, 0x32,
|
0xa9, 0x28, 0x4f, 0x57, 0x04, 0xab, 0x1c, 0x59, 0xcf, 0xe9, 0x2d, 0x51, 0xa4, 0xab, 0x58, 0xd9,
|
||||||
0x72, 0xc1, 0x5e, 0x93, 0x64, 0x45, 0x85, 0xee, 0xd2, 0x74, 0x0d, 0xaf, 0x87, 0xeb, 0x2a, 0xf4,
|
0xc8, 0x86, 0xf6, 0x8a, 0x24, 0x4b, 0xca, 0x35, 0x4b, 0xd3, 0x36, 0x9c, 0x2e, 0x2e, 0xbb, 0xd0,
|
||||||
0x3f, 0xc0, 0x8a, 0x47, 0x74, 0x41, 0x49, 0x34, 0x13, 0x8e, 0xa5, 0x62, 0x3b, 0xa5, 0x66, 0x9a,
|
0x53, 0x80, 0x25, 0x0b, 0xe9, 0x9c, 0x92, 0x70, 0xc6, 0xad, 0x9a, 0xaa, 0x6d, 0xe5, 0x9e, 0xa9,
|
||||||
0x2f, 0x23, 0x22, 0x31, 0x91, 0x24, 0x72, 0x5a, 0x7a, 0x19, 0x05, 0xac, 0xaf, 0x69, 0xfb, 0xd1,
|
0x5c, 0x46, 0x48, 0x22, 0x22, 0x48, 0x68, 0xd5, 0xf5, 0x32, 0x32, 0x88, 0x9c, 0xc7, 0x35, 0x35,
|
||||||
0x9a, 0xd0, 0x13, 0xd8, 0x61, 0x7c, 0x56, 0xaf, 0xdb, 0x56, 0x0e, 0x3d, 0xc6, 0x3f, 0xd4, 0x2a,
|
0x64, 0xc4, 0xdd, 0xdd, 0x6e, 0x06, 0x80, 0xbd, 0x9b, 0x89, 0xf6, 0x16, 0x6b, 0x43, 0xcf, 0x60,
|
||||||
0xd7, 0x18, 0xeb, 0xfc, 0x1d, 0x63, 0x7d, 0x68, 0x0b, 0x72, 0x95, 0x12, 0x16, 0x12, 0x07, 0x54,
|
0x37, 0x66, 0xb3, 0x32, 0x8f, 0xa6, 0x7a, 0xaa, 0x1b, 0xb3, 0x4f, 0x25, 0x26, 0xa5, 0x0b, 0xb6,
|
||||||
0xa7, 0x15, 0x46, 0x43, 0xb0, 0xab, 0x39, 0x98, 0x70, 0x6c, 0xd7, 0xf0, 0x2c, 0x5c, 0x8d, 0xf6,
|
0xfe, 0xed, 0x82, 0x3d, 0x68, 0x72, 0x72, 0xb5, 0x26, 0x71, 0x40, 0x2c, 0x50, 0xcc, 0x0b, 0x8c,
|
||||||
0x4e, 0xa0, 0x8f, 0x35, 0x87, 0x20, 0x73, 0xba, 0xae, 0xe1, 0x99, 0x93, 0xd7, 0x79, 0x81, 0xef,
|
0x06, 0xd0, 0x2e, 0xe6, 0x8a, 0xb9, 0xd5, 0xb6, 0x0d, 0xa7, 0x86, 0x8b, 0x51, 0x3f, 0x70, 0xf4,
|
||||||
0xf7, 0xc3, 0xa3, 0x7f, 0xb8, 0x41, 0x7f, 0x7a, 0xc1, 0x13, 0x79, 0x7a, 0xfc, 0x90, 0x7d, 0x92,
|
0xb9, 0x94, 0xe0, 0xa7, 0x56, 0xc7, 0x36, 0x1c, 0xd3, 0x7d, 0x2b, 0x1b, 0x7c, 0xdf, 0x0c, 0x8e,
|
||||||
0xa1, 0x31, 0x40, 0x10, 0xf3, 0xf0, 0x72, 0xa6, 0x28, 0xe8, 0xe5, 0xd5, 0x27, 0xbb, 0x9b, 0xfb,
|
0xff, 0x43, 0x93, 0xa3, 0xe9, 0x05, 0x4b, 0xc4, 0xe4, 0xe4, 0xf1, 0x75, 0x37, 0x45, 0x63, 0x00,
|
||||||
0x61, 0x17, 0xcf, 0x3f, 0x4d, 0x72, 0xc3, 0x94, 0xde, 0x10, 0xdc, 0x09, 0x4a, 0x31, 0x5f, 0x92,
|
0x3f, 0x62, 0xc1, 0xe5, 0x4c, 0x9d, 0xa4, 0x2b, 0xbb, 0xbb, 0x7b, 0xdb, 0xcd, 0xa0, 0x83, 0xbd,
|
||||||
0xc8, 0x56, 0x31, 0x65, 0x97, 0x33, 0x39, 0x4f, 0x96, 0x44, 0x3a, 0x7b, 0x8a, 0xf7, 0x5e, 0xa1,
|
0x1b, 0x57, 0x06, 0xa6, 0xf4, 0x96, 0xe0, 0x96, 0x9f, 0x9b, 0x72, 0x49, 0x3c, 0x5d, 0x46, 0x34,
|
||||||
0x3d, 0x53, 0xca, 0xe2, 0x60, 0xbe, 0x1a, 0xd0, 0x7a, 0xc3, 0x53, 0x26, 0x05, 0xda, 0x07, 0x6b,
|
0xbe, 0x9c, 0x09, 0x2f, 0x59, 0x10, 0x61, 0xed, 0x2b, 0x1d, 0x74, 0x33, 0xef, 0x99, 0x72, 0xca,
|
||||||
0x41, 0x63, 0x22, 0xd4, 0x99, 0x58, 0x58, 0x83, 0x9c, 0xe7, 0x88, 0x26, 0x6a, 0x69, 0x94, 0x08,
|
0x83, 0x46, 0x2c, 0xf0, 0xa2, 0xd9, 0x3c, 0xf2, 0x16, 0xdc, 0xfa, 0xd5, 0x50, 0x17, 0x05, 0xe5,
|
||||||
0x75, 0x2e, 0x16, 0xae, 0xab, 0xd4, 0xee, 0x74, 0x66, 0xa1, 0x2e, 0xc4, 0xc2, 0x15, 0xae, 0x93,
|
0x3b, 0x95, 0xae, 0x4c, 0x62, 0x5f, 0x0d, 0xa8, 0xbf, 0x63, 0xeb, 0x58, 0x70, 0x74, 0x00, 0xb5,
|
||||||
0x6c, 0x2a, 0x53, 0x45, 0xf2, 0x3e, 0x58, 0x41, 0x26, 0x49, 0x79, 0x18, 0x1a, 0x3c, 0xe2, 0xa1,
|
0x39, 0x8d, 0x08, 0x57, 0xc2, 0xaa, 0x61, 0x0d, 0xe4, 0x43, 0x21, 0x4d, 0xd4, 0x5a, 0x29, 0xe1,
|
||||||
0xf5, 0x07, 0x0f, 0x7d, 0x68, 0xeb, 0x3f, 0x3a, 0x3d, 0x56, 0x13, 0x75, 0x71, 0x85, 0x47, 0xef,
|
0x4a, 0x60, 0x35, 0x5c, 0x76, 0xa9, 0xed, 0xea, 0xde, 0x5c, 0x69, 0xaa, 0x86, 0x0b, 0x5c, 0x96,
|
||||||
0xa1, 0xa3, 0xa7, 0x98, 0x12, 0x89, 0x3c, 0x68, 0x85, 0x0a, 0x14, 0xbf, 0x03, 0xf9, 0xef, 0x68,
|
0x85, 0xa9, 0x42, 0x85, 0x2c, 0x0e, 0xa0, 0xe6, 0xa7, 0x82, 0xe4, 0x52, 0xd2, 0xe0, 0x8f, 0x4b,
|
||||||
0x73, 0xc1, 0x7b, 0x61, 0xcf, 0xdb, 0x0b, 0x13, 0x92, 0xff, 0x88, 0x1a, 0xac, 0x89, 0x4b, 0x38,
|
0xd5, 0xff, 0xba, 0x54, 0x0f, 0x9a, 0xfa, 0xe7, 0x4d, 0x4e, 0xd4, 0xcc, 0x1d, 0x5c, 0xe0, 0xe1,
|
||||||
0xd9, 0xbf, 0xfb, 0x39, 0x68, 0xdc, 0x6d, 0x06, 0xc6, 0xb7, 0xcd, 0xc0, 0xf8, 0xb1, 0x19, 0x34,
|
0x47, 0x68, 0xe9, 0x29, 0xa6, 0x44, 0x20, 0x07, 0xea, 0x81, 0x02, 0xd9, 0x6f, 0x03, 0xf9, 0xdb,
|
||||||
0x6e, 0x7f, 0x0d, 0x8c, 0xa0, 0xa5, 0x98, 0x3a, 0xfa, 0x1d, 0x00, 0x00, 0xff, 0xff, 0x28, 0xfa,
|
0x74, 0x38, 0x53, 0x46, 0x16, 0x97, 0xf4, 0x82, 0x84, 0xc8, 0x5f, 0xa5, 0x06, 0xab, 0xe2, 0x1c,
|
||||||
0x1e, 0x63, 0x9b, 0x04, 0x00, 0x00,
|
0xba, 0x07, 0xf7, 0x3f, 0xfa, 0x95, 0xfb, 0x6d, 0xdf, 0xf8, 0xb6, 0xed, 0x1b, 0x0f, 0xdb, 0x7e,
|
||||||
|
0xe5, 0xee, 0x67, 0xdf, 0xf0, 0xeb, 0xea, 0x96, 0xc7, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0x9a,
|
||||||
|
0x4b, 0x16, 0x44, 0xcd, 0x04, 0x00, 0x00,
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,14 +31,16 @@ message FileInfoTruncated {
|
||||||
int32 modified_ns = 11;
|
int32 modified_ns = 11;
|
||||||
uint64 modified_by = 12 [(gogoproto.customtype) = "github.com/syncthing/syncthing/lib/protocol.ShortID", (gogoproto.nullable) = false];
|
uint64 modified_by = 12 [(gogoproto.customtype) = "github.com/syncthing/syncthing/lib/protocol.ShortID", (gogoproto.nullable) = false];
|
||||||
bool deleted = 6;
|
bool deleted = 6;
|
||||||
bool invalid = 7;
|
bool invalid = 7 [(gogoproto.customname) = "RawInvalid"];
|
||||||
bool no_permissions = 8;
|
bool no_permissions = 8;
|
||||||
protocol.Vector version = 9 [(gogoproto.nullable) = false];
|
protocol.Vector version = 9 [(gogoproto.nullable) = false];
|
||||||
int64 sequence = 10;
|
int64 sequence = 10;
|
||||||
int32 block_size = 13 [(gogoproto.customname) = "RawBlockSize"];
|
int32 block_size = 13 [(gogoproto.customname) = "RawBlockSize"];
|
||||||
|
|
||||||
// repeated BlockInfo Blocks = 16
|
// repeated BlockInfo Blocks = 16
|
||||||
string symlink_target = 17;
|
string symlink_target = 17;
|
||||||
|
|
||||||
|
// see bep.proto
|
||||||
|
uint32 local_flags = 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For each folder and device we keep one of these to track the current
|
// For each folder and device we keep one of these to track the current
|
||||||
|
|
|
@ -60,7 +60,7 @@ func (f *sendOnlyFolder) pull() bool {
|
||||||
|
|
||||||
if ignores.ShouldIgnore(intf.FileName()) {
|
if ignores.ShouldIgnore(intf.FileName()) {
|
||||||
file := intf.(protocol.FileInfo)
|
file := intf.(protocol.FileInfo)
|
||||||
file.Invalidate(f.shortID)
|
file.SetIgnored(f.shortID)
|
||||||
batch = append(batch, file)
|
batch = append(batch, file)
|
||||||
batchSizeBytes += file.ProtoSize()
|
batchSizeBytes += file.ProtoSize()
|
||||||
l.Debugln(f, "Handling ignored file", file)
|
l.Debugln(f, "Handling ignored file", file)
|
||||||
|
|
|
@ -269,7 +269,7 @@ func (f *sendReceiveFolder) pullerIteration(ignores *ignore.Matcher, ignoresChan
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case ignores.ShouldIgnore(file.Name):
|
case ignores.ShouldIgnore(file.Name):
|
||||||
file.Invalidate(f.shortID)
|
file.SetIgnored(f.shortID)
|
||||||
l.Debugln(f, "Handling ignored file", file)
|
l.Debugln(f, "Handling ignored file", file)
|
||||||
dbUpdateChan <- dbUpdateJob{file, dbUpdateInvalidate}
|
dbUpdateChan <- dbUpdateJob{file, dbUpdateInvalidate}
|
||||||
changed++
|
changed++
|
||||||
|
@ -297,7 +297,7 @@ func (f *sendReceiveFolder) pullerIteration(ignores *ignore.Matcher, ignoresChan
|
||||||
l.Debugln(f, "Needed file is unavailable", file)
|
l.Debugln(f, "Needed file is unavailable", file)
|
||||||
|
|
||||||
case runtime.GOOS == "windows" && file.IsSymlink():
|
case runtime.GOOS == "windows" && file.IsSymlink():
|
||||||
file.Invalidate(f.shortID)
|
file.SetUnsupported(f.shortID)
|
||||||
l.Debugln(f, "Invalidating symlink (unsupported)", file.Name)
|
l.Debugln(f, "Invalidating symlink (unsupported)", file.Name)
|
||||||
dbUpdateChan <- dbUpdateJob{file, dbUpdateInvalidate}
|
dbUpdateChan <- dbUpdateJob{file, dbUpdateInvalidate}
|
||||||
changed++
|
changed++
|
||||||
|
|
|
@ -862,6 +862,11 @@ func (m *Model) handleIndex(deviceID protocol.DeviceID, folder string, fs []prot
|
||||||
if !update {
|
if !update {
|
||||||
files.Drop(deviceID)
|
files.Drop(deviceID)
|
||||||
}
|
}
|
||||||
|
for i := range fs {
|
||||||
|
// The local flags should never be transmitted over the wire. Make
|
||||||
|
// sure they look like they weren't.
|
||||||
|
fs[i].LocalFlags = 0
|
||||||
|
}
|
||||||
files.Update(deviceID, fs)
|
files.Update(deviceID, fs)
|
||||||
|
|
||||||
events.Default.Log(events.RemoteIndexUpdated, map[string]interface{}{
|
events.Default.Log(events.RemoteIndexUpdated, map[string]interface{}{
|
||||||
|
@ -1389,7 +1394,7 @@ func (m *Model) recheckFile(deviceID protocol.DeviceID, folderFs fs.Filesystem,
|
||||||
// The hashes provided part of the request match what we expect to find according
|
// The hashes provided part of the request match what we expect to find according
|
||||||
// to what we have in the database, yet the content we've read off the filesystem doesn't
|
// to what we have in the database, yet the content we've read off the filesystem doesn't
|
||||||
// Something is fishy, invalidate the file and rescan it.
|
// Something is fishy, invalidate the file and rescan it.
|
||||||
cf.Invalidate(m.shortID)
|
cf.SetMustRescan(m.shortID)
|
||||||
|
|
||||||
// Update the index and tell others
|
// Update the index and tell others
|
||||||
// The file will temporarily become invalid, which is ok as the content is messed up.
|
// The file will temporarily become invalid, which is ok as the content is messed up.
|
||||||
|
@ -1736,6 +1741,10 @@ func sendIndexTo(prevSequence int64, conn protocol.Connection, folder string, fs
|
||||||
|
|
||||||
f = fi.(protocol.FileInfo)
|
f = fi.(protocol.FileInfo)
|
||||||
|
|
||||||
|
// Mark the file as invalid if any of the local bad stuff flags are set.
|
||||||
|
f.RawInvalid = f.IsInvalid()
|
||||||
|
f.LocalFlags = 0 // never sent externally
|
||||||
|
|
||||||
if dropSymlinks && f.IsSymlink() {
|
if dropSymlinks && f.IsSymlink() {
|
||||||
// Do not send index entries with symlinks to clients that can't
|
// Do not send index entries with symlinks to clients that can't
|
||||||
// handle it. Fixes issue #3802. Once both sides are upgraded, a
|
// handle it. Fixes issue #3802. Once both sides are upgraded, a
|
||||||
|
@ -2064,23 +2073,23 @@ func (m *Model) internalScanFolderSubdirs(ctx context.Context, folder string, su
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case !f.IsInvalid() && ignores.Match(f.Name).IsIgnored():
|
case !f.IsIgnored() && ignores.Match(f.Name).IsIgnored():
|
||||||
// File was valid at last pass but has been ignored. Set invalid bit.
|
// File was not ignored at last pass but has been ignored.
|
||||||
l.Debugln("setting invalid bit on ignored", f)
|
l.Debugln("marking file as ignored", f)
|
||||||
nf := f.ConvertToInvalidFileInfo(m.id.Short())
|
nf := f.ConvertToIgnoredFileInfo(m.id.Short())
|
||||||
batch = append(batch, nf)
|
batch = append(batch, nf)
|
||||||
batchSizeBytes += nf.ProtoSize()
|
batchSizeBytes += nf.ProtoSize()
|
||||||
changes++
|
changes++
|
||||||
|
|
||||||
case f.IsInvalid() && !ignores.Match(f.Name).IsIgnored():
|
case f.IsIgnored() && !ignores.Match(f.Name).IsIgnored():
|
||||||
// Successfully scanned items are already un-ignored during
|
// Successfully scanned items are already un-ignored during
|
||||||
// the scan, so check whether it is deleted.
|
// the scan, so check whether it is deleted.
|
||||||
fallthrough
|
fallthrough
|
||||||
case !f.IsInvalid() && !f.IsDeleted():
|
case !f.IsIgnored() && !f.IsDeleted():
|
||||||
// The file is valid and not deleted. Lets check if it's
|
// The file is not ignored and not deleted. Lets check if
|
||||||
// still here.
|
// it's still here. Simply stat:ing it wont do as there are
|
||||||
// Simply stating it wont do as there are tons of corner
|
// tons of corner cases (e.g. parent dir->symlink, missing
|
||||||
// cases (e.g. parent dir->simlink, missing permissions)
|
// permissions)
|
||||||
if !osutil.IsDeleted(mtimefs, f.Name) {
|
if !osutil.IsDeleted(mtimefs, f.Name) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -2099,7 +2108,7 @@ func (m *Model) internalScanFolderSubdirs(ctx context.Context, folder string, su
|
||||||
// counter makes sure we are in conflict with any
|
// counter makes sure we are in conflict with any
|
||||||
// other existing versions, which will be resolved
|
// other existing versions, which will be resolved
|
||||||
// by the normal pulling mechanisms.
|
// by the normal pulling mechanisms.
|
||||||
if f.IsInvalid() {
|
if f.IsIgnored() {
|
||||||
nf.Version = nf.Version.DropOthers(m.shortID)
|
nf.Version = nf.Version.DropOthers(m.shortID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -179,7 +179,7 @@ func TestRequestCreateTmpSymlink(t *testing.T) {
|
||||||
fc.indexFn = func(folder string, fs []protocol.FileInfo) {
|
fc.indexFn = func(folder string, fs []protocol.FileInfo) {
|
||||||
for _, f := range fs {
|
for _, f := range fs {
|
||||||
if f.Name == name {
|
if f.Name == name {
|
||||||
if f.Invalid {
|
if f.IsInvalid() {
|
||||||
goodIdx <- struct{}{}
|
goodIdx <- struct{}{}
|
||||||
} else {
|
} else {
|
||||||
t.Fatal("Received index with non-invalid temporary file")
|
t.Fatal("Received index with non-invalid temporary file")
|
||||||
|
@ -348,7 +348,7 @@ func pullInvalidIgnored(t *testing.T, ft config.FolderType) {
|
||||||
if _, ok := expected[f.Name]; !ok {
|
if _, ok := expected[f.Name]; !ok {
|
||||||
t.Errorf("Unexpected file %v was added to index", f.Name)
|
t.Errorf("Unexpected file %v was added to index", f.Name)
|
||||||
}
|
}
|
||||||
if !f.Invalid {
|
if !f.IsInvalid() {
|
||||||
t.Errorf("File %v wasn't marked as invalid", f.Name)
|
t.Errorf("File %v wasn't marked as invalid", f.Name)
|
||||||
}
|
}
|
||||||
delete(expected, f.Name)
|
delete(expected, f.Name)
|
||||||
|
@ -382,7 +382,7 @@ func pullInvalidIgnored(t *testing.T, ft config.FolderType) {
|
||||||
if _, ok := expected[f.Name]; !ok {
|
if _, ok := expected[f.Name]; !ok {
|
||||||
t.Fatalf("Unexpected file %v was updated in index", f.Name)
|
t.Fatalf("Unexpected file %v was updated in index", f.Name)
|
||||||
}
|
}
|
||||||
if f.Invalid {
|
if f.IsInvalid() {
|
||||||
t.Errorf("File %v is still marked as invalid", f.Name)
|
t.Errorf("File %v is still marked as invalid", f.Name)
|
||||||
}
|
}
|
||||||
// The unignored files should only have a local version,
|
// The unignored files should only have a local version,
|
||||||
|
@ -448,7 +448,7 @@ func TestIssue4841(t *testing.T) {
|
||||||
m.updateLocals(defaultFolderConfig.ID, []protocol.FileInfo{{
|
m.updateLocals(defaultFolderConfig.ID, []protocol.FileInfo{{
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Type: protocol.FileInfoTypeFile,
|
Type: protocol.FileInfoTypeFile,
|
||||||
Invalid: true,
|
LocalFlags: protocol.FlagLocalIgnored,
|
||||||
Version: protocol.Vector{}.Update(device2.Short()),
|
Version: protocol.Vector{}.Update(device2.Short()),
|
||||||
}})
|
}})
|
||||||
<-received
|
<-received
|
||||||
|
|
|
@ -302,13 +302,18 @@ type FileInfo struct {
|
||||||
ModifiedNs int32 `protobuf:"varint,11,opt,name=modified_ns,json=modifiedNs,proto3" json:"modified_ns,omitempty"`
|
ModifiedNs int32 `protobuf:"varint,11,opt,name=modified_ns,json=modifiedNs,proto3" json:"modified_ns,omitempty"`
|
||||||
ModifiedBy ShortID `protobuf:"varint,12,opt,name=modified_by,json=modifiedBy,proto3,customtype=ShortID" json:"modified_by"`
|
ModifiedBy ShortID `protobuf:"varint,12,opt,name=modified_by,json=modifiedBy,proto3,customtype=ShortID" json:"modified_by"`
|
||||||
Deleted bool `protobuf:"varint,6,opt,name=deleted,proto3" json:"deleted,omitempty"`
|
Deleted bool `protobuf:"varint,6,opt,name=deleted,proto3" json:"deleted,omitempty"`
|
||||||
Invalid bool `protobuf:"varint,7,opt,name=invalid,proto3" json:"invalid,omitempty"`
|
RawInvalid bool `protobuf:"varint,7,opt,name=invalid,proto3" json:"invalid,omitempty"`
|
||||||
NoPermissions bool `protobuf:"varint,8,opt,name=no_permissions,json=noPermissions,proto3" json:"no_permissions,omitempty"`
|
NoPermissions bool `protobuf:"varint,8,opt,name=no_permissions,json=noPermissions,proto3" json:"no_permissions,omitempty"`
|
||||||
Version Vector `protobuf:"bytes,9,opt,name=version" json:"version"`
|
Version Vector `protobuf:"bytes,9,opt,name=version" json:"version"`
|
||||||
Sequence int64 `protobuf:"varint,10,opt,name=sequence,proto3" json:"sequence,omitempty"`
|
Sequence int64 `protobuf:"varint,10,opt,name=sequence,proto3" json:"sequence,omitempty"`
|
||||||
RawBlockSize int32 `protobuf:"varint,13,opt,name=block_size,json=blockSize,proto3" json:"block_size,omitempty"`
|
RawBlockSize int32 `protobuf:"varint,13,opt,name=block_size,json=blockSize,proto3" json:"block_size,omitempty"`
|
||||||
Blocks []BlockInfo `protobuf:"bytes,16,rep,name=Blocks" json:"Blocks"`
|
Blocks []BlockInfo `protobuf:"bytes,16,rep,name=Blocks" json:"Blocks"`
|
||||||
SymlinkTarget string `protobuf:"bytes,17,opt,name=symlink_target,json=symlinkTarget,proto3" json:"symlink_target,omitempty"`
|
SymlinkTarget string `protobuf:"bytes,17,opt,name=symlink_target,json=symlinkTarget,proto3" json:"symlink_target,omitempty"`
|
||||||
|
// 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 `protobuf:"varint,1000,opt,name=local_flags,json=localFlags,proto3" json:"local_flags,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *FileInfo) Reset() { *m = FileInfo{} }
|
func (m *FileInfo) Reset() { *m = FileInfo{} }
|
||||||
|
@ -835,10 +840,10 @@ func (m *FileInfo) MarshalTo(dAtA []byte) (int, error) {
|
||||||
}
|
}
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
if m.Invalid {
|
if m.RawInvalid {
|
||||||
dAtA[i] = 0x38
|
dAtA[i] = 0x38
|
||||||
i++
|
i++
|
||||||
if m.Invalid {
|
if m.RawInvalid {
|
||||||
dAtA[i] = 1
|
dAtA[i] = 1
|
||||||
} else {
|
} else {
|
||||||
dAtA[i] = 0
|
dAtA[i] = 0
|
||||||
|
@ -905,6 +910,13 @@ func (m *FileInfo) MarshalTo(dAtA []byte) (int, error) {
|
||||||
i = encodeVarintBep(dAtA, i, uint64(len(m.SymlinkTarget)))
|
i = encodeVarintBep(dAtA, i, uint64(len(m.SymlinkTarget)))
|
||||||
i += copy(dAtA[i:], m.SymlinkTarget)
|
i += copy(dAtA[i:], m.SymlinkTarget)
|
||||||
}
|
}
|
||||||
|
if m.LocalFlags != 0 {
|
||||||
|
dAtA[i] = 0xc0
|
||||||
|
i++
|
||||||
|
dAtA[i] = 0x3e
|
||||||
|
i++
|
||||||
|
i = encodeVarintBep(dAtA, i, uint64(m.LocalFlags))
|
||||||
|
}
|
||||||
return i, nil
|
return i, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1422,7 +1434,7 @@ func (m *FileInfo) ProtoSize() (n int) {
|
||||||
if m.Deleted {
|
if m.Deleted {
|
||||||
n += 2
|
n += 2
|
||||||
}
|
}
|
||||||
if m.Invalid {
|
if m.RawInvalid {
|
||||||
n += 2
|
n += 2
|
||||||
}
|
}
|
||||||
if m.NoPermissions {
|
if m.NoPermissions {
|
||||||
|
@ -1452,6 +1464,9 @@ func (m *FileInfo) ProtoSize() (n int) {
|
||||||
if l > 0 {
|
if l > 0 {
|
||||||
n += 2 + l + sovBep(uint64(l))
|
n += 2 + l + sovBep(uint64(l))
|
||||||
}
|
}
|
||||||
|
if m.LocalFlags != 0 {
|
||||||
|
n += 2 + sovBep(uint64(m.LocalFlags))
|
||||||
|
}
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2797,7 +2812,7 @@ func (m *FileInfo) Unmarshal(dAtA []byte) error {
|
||||||
m.Deleted = bool(v != 0)
|
m.Deleted = bool(v != 0)
|
||||||
case 7:
|
case 7:
|
||||||
if wireType != 0 {
|
if wireType != 0 {
|
||||||
return fmt.Errorf("proto: wrong wireType = %d for field Invalid", wireType)
|
return fmt.Errorf("proto: wrong wireType = %d for field RawInvalid", wireType)
|
||||||
}
|
}
|
||||||
var v int
|
var v int
|
||||||
for shift := uint(0); ; shift += 7 {
|
for shift := uint(0); ; shift += 7 {
|
||||||
|
@ -2814,7 +2829,7 @@ func (m *FileInfo) Unmarshal(dAtA []byte) error {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m.Invalid = bool(v != 0)
|
m.RawInvalid = bool(v != 0)
|
||||||
case 8:
|
case 8:
|
||||||
if wireType != 0 {
|
if wireType != 0 {
|
||||||
return fmt.Errorf("proto: wrong wireType = %d for field NoPermissions", wireType)
|
return fmt.Errorf("proto: wrong wireType = %d for field NoPermissions", wireType)
|
||||||
|
@ -3001,6 +3016,25 @@ func (m *FileInfo) Unmarshal(dAtA []byte) error {
|
||||||
}
|
}
|
||||||
m.SymlinkTarget = string(dAtA[iNdEx:postIndex])
|
m.SymlinkTarget = string(dAtA[iNdEx:postIndex])
|
||||||
iNdEx = postIndex
|
iNdEx = postIndex
|
||||||
|
case 1000:
|
||||||
|
if wireType != 0 {
|
||||||
|
return fmt.Errorf("proto: wrong wireType = %d for field LocalFlags", wireType)
|
||||||
|
}
|
||||||
|
m.LocalFlags = 0
|
||||||
|
for shift := uint(0); ; shift += 7 {
|
||||||
|
if shift >= 64 {
|
||||||
|
return ErrIntOverflowBep
|
||||||
|
}
|
||||||
|
if iNdEx >= l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
b := dAtA[iNdEx]
|
||||||
|
iNdEx++
|
||||||
|
m.LocalFlags |= (uint32(b) & 0x7F) << shift
|
||||||
|
if b < 0x80 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
iNdEx = preIndex
|
iNdEx = preIndex
|
||||||
skippy, err := skipBep(dAtA[iNdEx:])
|
skippy, err := skipBep(dAtA[iNdEx:])
|
||||||
|
@ -4220,116 +4254,118 @@ var (
|
||||||
func init() { proto.RegisterFile("bep.proto", fileDescriptorBep) }
|
func init() { proto.RegisterFile("bep.proto", fileDescriptorBep) }
|
||||||
|
|
||||||
var fileDescriptorBep = []byte{
|
var fileDescriptorBep = []byte{
|
||||||
// 1762 bytes of a gzipped FileDescriptorProto
|
// 1793 bytes of a gzipped FileDescriptorProto
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0x4f, 0x8f, 0xdb, 0xc6,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0x4f, 0x73, 0xdb, 0xc6,
|
||||||
0x15, 0x5f, 0x4a, 0x94, 0x44, 0x3d, 0x69, 0x37, 0xdc, 0xb1, 0xbd, 0x65, 0x99, 0x8d, 0x44, 0x2b,
|
0x15, 0x17, 0x48, 0xf0, 0xdf, 0x23, 0xa5, 0x40, 0x6b, 0x5b, 0x45, 0x11, 0x85, 0x84, 0x19, 0x3b,
|
||||||
0x76, 0xbc, 0x59, 0x24, 0x6b, 0x37, 0x49, 0x5b, 0xb4, 0x68, 0x0b, 0xe8, 0x0f, 0x77, 0x2d, 0x54,
|
0x56, 0x34, 0x89, 0xec, 0x26, 0x69, 0x3b, 0xed, 0xb4, 0x9d, 0xe1, 0x1f, 0x48, 0xe6, 0x54, 0x26,
|
||||||
0xa6, 0xd4, 0x91, 0xd6, 0xa9, 0x73, 0x28, 0x41, 0x89, 0x23, 0x2d, 0x61, 0x8a, 0xa3, 0x92, 0xd4,
|
0xd9, 0x25, 0xe5, 0xd4, 0x39, 0x14, 0x03, 0x12, 0x4b, 0x0a, 0x63, 0x10, 0xcb, 0x02, 0xa0, 0x64,
|
||||||
0xda, 0xca, 0x47, 0xd0, 0x27, 0xe8, 0x45, 0x40, 0x80, 0x9e, 0x0a, 0xf4, 0x83, 0xf8, 0x98, 0xf6,
|
0xe6, 0x23, 0xf0, 0x13, 0xf4, 0xc2, 0x99, 0xcc, 0xf4, 0xd4, 0x6f, 0xe2, 0x63, 0xda, 0x43, 0x0f,
|
||||||
0xd0, 0x43, 0x0f, 0x46, 0xb3, 0xbd, 0xf4, 0xd8, 0x4f, 0x50, 0x14, 0x9c, 0x21, 0x25, 0x6a, 0xd7,
|
0x3d, 0x68, 0x1a, 0xf5, 0x92, 0x63, 0x3f, 0x41, 0xa7, 0xb3, 0xbb, 0x00, 0x09, 0x4a, 0x76, 0xc6,
|
||||||
0x0e, 0x7c, 0xc8, 0x89, 0x33, 0xef, 0xfd, 0xe6, 0x0d, 0xdf, 0x6f, 0x7e, 0xef, 0xcd, 0x40, 0x71,
|
0x87, 0x9c, 0xb8, 0xfb, 0xde, 0x6f, 0xdf, 0xf2, 0xfd, 0xde, 0xef, 0xbd, 0x05, 0x14, 0x06, 0x64,
|
||||||
0x48, 0x66, 0x27, 0x33, 0x9f, 0x86, 0x14, 0x49, 0xec, 0x33, 0xa2, 0xae, 0xfa, 0xe9, 0xc4, 0x09,
|
0x7a, 0x34, 0xf5, 0x69, 0x48, 0x51, 0x9e, 0xff, 0x0c, 0xa9, 0xab, 0x7d, 0x3a, 0x76, 0xc2, 0xf3,
|
||||||
0x2f, 0xe6, 0xc3, 0x93, 0x11, 0x9d, 0x3e, 0x9c, 0xd0, 0x09, 0x7d, 0xc8, 0x3c, 0xc3, 0xf9, 0x98,
|
0xd9, 0xe0, 0x68, 0x48, 0x27, 0x8f, 0xc7, 0x74, 0x4c, 0x1f, 0x73, 0xcf, 0x60, 0x36, 0xe2, 0x3b,
|
||||||
0xcd, 0xd8, 0x84, 0x8d, 0xf8, 0xc2, 0xda, 0x0c, 0x72, 0x8f, 0x89, 0xeb, 0x52, 0x54, 0x85, 0x92,
|
0xbe, 0xe1, 0x2b, 0x71, 0xb0, 0x3a, 0x85, 0xcc, 0x53, 0xe2, 0xba, 0x14, 0x55, 0xa0, 0x68, 0x93,
|
||||||
0x4d, 0x2e, 0x9d, 0x11, 0x31, 0x3d, 0x6b, 0x4a, 0x14, 0x41, 0x13, 0x8e, 0x8a, 0x18, 0xb8, 0xc9,
|
0x0b, 0x67, 0x48, 0x4c, 0xcf, 0x9a, 0x10, 0x55, 0xd2, 0xa5, 0x83, 0x02, 0x06, 0x61, 0x6a, 0x5b,
|
||||||
0xb0, 0xa6, 0x24, 0x02, 0x8c, 0x5c, 0x87, 0x78, 0x21, 0x07, 0x64, 0x38, 0x80, 0x9b, 0x18, 0xe0,
|
0x13, 0xc2, 0x00, 0x43, 0xd7, 0x21, 0x5e, 0x28, 0x00, 0x29, 0x01, 0x10, 0x26, 0x0e, 0x78, 0x08,
|
||||||
0x3e, 0xec, 0xc5, 0x80, 0x4b, 0xe2, 0x07, 0x0e, 0xf5, 0x94, 0x2c, 0xc3, 0xec, 0x72, 0xeb, 0x53,
|
0x3b, 0x11, 0xe0, 0x82, 0xf8, 0x81, 0x43, 0x3d, 0x35, 0xcd, 0x31, 0xdb, 0xc2, 0xfa, 0x5c, 0x18,
|
||||||
0x6e, 0xac, 0x05, 0x90, 0x7f, 0x4c, 0x2c, 0x9b, 0xf8, 0xe8, 0x63, 0x10, 0xc3, 0xc5, 0x8c, 0xef,
|
0xab, 0x01, 0x64, 0x9f, 0x12, 0xcb, 0x26, 0x3e, 0xfa, 0x18, 0xe4, 0x70, 0x3e, 0x15, 0x77, 0xed,
|
||||||
0xb5, 0xf7, 0xd9, 0x9d, 0x93, 0x24, 0x87, 0x93, 0x27, 0x24, 0x08, 0xac, 0x09, 0x19, 0x2c, 0x66,
|
0x7c, 0x76, 0xef, 0x28, 0xce, 0xe1, 0xe8, 0x19, 0x09, 0x02, 0x6b, 0x4c, 0xfa, 0xf3, 0x29, 0xc1,
|
||||||
0x04, 0x33, 0x08, 0xfa, 0x0d, 0x94, 0x46, 0x74, 0x3a, 0xf3, 0x49, 0xc0, 0x02, 0x67, 0xd8, 0x8a,
|
0x1c, 0x82, 0x7e, 0x07, 0xc5, 0x21, 0x9d, 0x4c, 0x7d, 0x12, 0xf0, 0xc0, 0x29, 0x7e, 0x62, 0xff,
|
||||||
0xc3, 0x1b, 0x2b, 0x9a, 0x1b, 0x0c, 0x4e, 0x2f, 0xa8, 0xd5, 0x61, 0xb7, 0xe9, 0xce, 0x83, 0x90,
|
0xd6, 0x89, 0xc6, 0x1a, 0x83, 0x93, 0x07, 0xaa, 0x35, 0xd8, 0x6e, 0xb8, 0xb3, 0x20, 0x24, 0x7e,
|
||||||
0xf8, 0x4d, 0xea, 0x8d, 0x9d, 0x09, 0x7a, 0x04, 0x85, 0x31, 0x75, 0x6d, 0xe2, 0x07, 0x8a, 0xa0,
|
0x83, 0x7a, 0x23, 0x67, 0x8c, 0x9e, 0x40, 0x6e, 0x44, 0x5d, 0x9b, 0xf8, 0x81, 0x2a, 0xe9, 0xe9,
|
||||||
0x65, 0x8f, 0x4a, 0x9f, 0xc9, 0x9b, 0x60, 0xa7, 0xcc, 0xd1, 0x10, 0x5f, 0xbd, 0xae, 0xee, 0xe0,
|
0x83, 0xe2, 0x67, 0xca, 0x3a, 0xd8, 0x31, 0x77, 0xd4, 0xe5, 0xd7, 0x57, 0x95, 0x2d, 0x1c, 0xc3,
|
||||||
0x04, 0x56, 0xfb, 0x73, 0x06, 0xf2, 0xdc, 0x83, 0x0e, 0x20, 0xe3, 0xd8, 0x9c, 0xa2, 0x46, 0xfe,
|
0xaa, 0x7f, 0x4d, 0x41, 0x56, 0x78, 0xd0, 0x1e, 0xa4, 0x1c, 0x5b, 0x50, 0x54, 0xcf, 0x5e, 0x5f,
|
||||||
0xea, 0x75, 0x35, 0xd3, 0x6e, 0xe1, 0x8c, 0x63, 0xa3, 0xdb, 0x90, 0x73, 0xad, 0x21, 0x71, 0x63,
|
0x55, 0x52, 0xad, 0x26, 0x4e, 0x39, 0x36, 0xba, 0x0b, 0x19, 0xd7, 0x1a, 0x10, 0x37, 0x22, 0x47,
|
||||||
0x72, 0xf8, 0x04, 0xbd, 0x0f, 0x45, 0x9f, 0x58, 0xb6, 0x49, 0x3d, 0x77, 0xc1, 0x28, 0x91, 0xb0,
|
0x6c, 0xd0, 0xfb, 0x50, 0xf0, 0x89, 0x65, 0x9b, 0xd4, 0x73, 0xe7, 0x9c, 0x92, 0x3c, 0xce, 0x33,
|
||||||
0x14, 0x19, 0xba, 0x9e, 0xbb, 0x40, 0x9f, 0x02, 0x72, 0x26, 0x1e, 0xf5, 0x89, 0x39, 0x23, 0xfe,
|
0x43, 0xc7, 0x73, 0xe7, 0xe8, 0x53, 0x40, 0xce, 0xd8, 0xa3, 0x3e, 0x31, 0xa7, 0xc4, 0x9f, 0x38,
|
||||||
0xd4, 0x61, 0x7f, 0x1b, 0x28, 0x22, 0x43, 0xed, 0x73, 0x4f, 0x6f, 0xe3, 0x40, 0x1f, 0xc2, 0x6e,
|
0xfc, 0xdf, 0x06, 0xaa, 0xcc, 0x51, 0xbb, 0xc2, 0xd3, 0x5d, 0x3b, 0xd0, 0x87, 0xb0, 0x1d, 0xc1,
|
||||||
0x0c, 0xb7, 0x89, 0x4b, 0x42, 0xa2, 0xe4, 0x18, 0xb2, 0xcc, 0x8d, 0x2d, 0x66, 0x43, 0x8f, 0xe0,
|
0x6d, 0xe2, 0x92, 0x90, 0xa8, 0x19, 0x8e, 0x2c, 0x09, 0x63, 0x93, 0xdb, 0xd0, 0x13, 0xb8, 0x6b,
|
||||||
0xb6, 0xed, 0x04, 0xd6, 0xd0, 0x25, 0x66, 0x48, 0xa6, 0x33, 0xd3, 0xf1, 0x6c, 0xf2, 0x92, 0x04,
|
0x3b, 0x81, 0x35, 0x70, 0x89, 0x19, 0x92, 0xc9, 0xd4, 0x74, 0x3c, 0x9b, 0xbc, 0x22, 0x81, 0x9a,
|
||||||
0x4a, 0x9e, 0x61, 0x51, 0xec, 0x1b, 0x90, 0xe9, 0xac, 0xcd, 0x3d, 0xe8, 0x00, 0xf2, 0x33, 0x6b,
|
0xe5, 0x58, 0x14, 0xf9, 0xfa, 0x64, 0x32, 0x6d, 0x09, 0x0f, 0xda, 0x83, 0xec, 0xd4, 0x9a, 0x05,
|
||||||
0x1e, 0x10, 0x5b, 0x29, 0x30, 0x4c, 0x3c, 0x8b, 0x58, 0xe2, 0x0a, 0x08, 0x14, 0xf9, 0x3a, 0x4b,
|
0xc4, 0x56, 0x73, 0x1c, 0x13, 0xed, 0x18, 0x4b, 0x42, 0x01, 0x81, 0xaa, 0xdc, 0x64, 0xa9, 0xc9,
|
||||||
0x2d, 0xe6, 0x48, 0x58, 0x8a, 0x61, 0xb5, 0xff, 0x66, 0x20, 0xcf, 0x3d, 0xe8, 0xa3, 0x35, 0x4b,
|
0x1d, 0x31, 0x4b, 0x11, 0xac, 0xfa, 0xdf, 0x14, 0x64, 0x85, 0x07, 0x7d, 0xb4, 0x62, 0xa9, 0x54,
|
||||||
0xe5, 0xc6, 0x41, 0x84, 0xfa, 0xe7, 0xeb, 0xaa, 0xc4, 0x7d, 0xed, 0x56, 0x8a, 0x35, 0x04, 0x62,
|
0xdf, 0x63, 0xa8, 0x7f, 0x5d, 0x55, 0xf2, 0xc2, 0xd7, 0x6a, 0x26, 0x58, 0x43, 0x20, 0x27, 0x14,
|
||||||
0x4a, 0x51, 0x6c, 0x8c, 0x0e, 0xa1, 0x68, 0xd9, 0x76, 0x74, 0x7a, 0x24, 0x50, 0xb2, 0x5a, 0xf6,
|
0xc5, 0xd7, 0x68, 0x1f, 0x0a, 0x96, 0x6d, 0xb3, 0xea, 0x91, 0x40, 0x4d, 0xeb, 0xe9, 0x83, 0x02,
|
||||||
0xa8, 0x88, 0x37, 0x06, 0xf4, 0xf3, 0x6d, 0x35, 0x88, 0xd7, 0xf5, 0xf3, 0x36, 0x19, 0x44, 0x47,
|
0x5e, 0x1b, 0xd0, 0x2f, 0x37, 0xd5, 0x20, 0xdf, 0xd4, 0xcf, 0xdb, 0x64, 0xc0, 0x4a, 0x31, 0x24,
|
||||||
0x31, 0x22, 0x7e, 0xac, 0xe0, 0x1c, 0xdb, 0x4f, 0x8a, 0x0c, 0x4c, 0xbf, 0x77, 0xa1, 0x3c, 0xb5,
|
0x7e, 0xa4, 0xe0, 0x0c, 0xbf, 0x2f, 0xcf, 0x0c, 0x5c, 0xbf, 0xf7, 0xa1, 0x34, 0xb1, 0x5e, 0x99,
|
||||||
0x5e, 0x9a, 0x01, 0xf9, 0xe3, 0x9c, 0x78, 0x23, 0xc2, 0xe8, 0xca, 0xe2, 0xd2, 0xd4, 0x7a, 0xd9,
|
0x01, 0xf9, 0xf3, 0x8c, 0x78, 0x43, 0xc2, 0xe9, 0x4a, 0xe3, 0xe2, 0xc4, 0x7a, 0xd5, 0x8b, 0x4c,
|
||||||
0x8f, 0x4d, 0xa8, 0x02, 0xe0, 0x78, 0xa1, 0x4f, 0xed, 0xf9, 0x88, 0xf8, 0x31, 0x57, 0x29, 0x0b,
|
0xa8, 0x0c, 0xe0, 0x78, 0xa1, 0x4f, 0xed, 0xd9, 0x90, 0xf8, 0x11, 0x57, 0x09, 0x0b, 0xfa, 0x39,
|
||||||
0xfa, 0x29, 0x48, 0x8c, 0x6c, 0xd3, 0xb1, 0x15, 0x49, 0x13, 0x8e, 0xc4, 0x86, 0x1a, 0x27, 0x5e,
|
0xe4, 0x39, 0xd9, 0xa6, 0x63, 0xab, 0x79, 0x5d, 0x3a, 0x90, 0xeb, 0x5a, 0x94, 0x78, 0x8e, 0x53,
|
||||||
0x60, 0x54, 0xb3, 0xbc, 0x93, 0x21, 0x2e, 0x30, 0x6c, 0xdb, 0x46, 0xbf, 0x02, 0x35, 0x78, 0xee,
|
0xcd, 0xf3, 0x8e, 0x97, 0x38, 0xc7, 0xb1, 0x2d, 0x1b, 0xfd, 0x06, 0xb4, 0xe0, 0xa5, 0xc3, 0x0a,
|
||||||
0x44, 0x07, 0xc5, 0x23, 0x85, 0x0e, 0xf5, 0x4c, 0x9f, 0x4c, 0xe9, 0xa5, 0xe5, 0x06, 0x4a, 0x91,
|
0x25, 0x22, 0x85, 0x0e, 0xf5, 0x4c, 0x9f, 0x4c, 0xe8, 0x85, 0xe5, 0x06, 0x6a, 0x81, 0x5f, 0xa3,
|
||||||
0x6d, 0xa3, 0x44, 0x88, 0x76, 0x0a, 0x80, 0x63, 0x7f, 0xad, 0x0b, 0x39, 0x16, 0x31, 0x3a, 0x45,
|
0x32, 0x44, 0x2b, 0x01, 0xc0, 0x91, 0xbf, 0xda, 0x81, 0x0c, 0x8f, 0xc8, 0xaa, 0x28, 0xc4, 0x1a,
|
||||||
0x2e, 0xd6, 0xb8, 0x7a, 0xe3, 0x19, 0x3a, 0x81, 0xdc, 0xd8, 0x71, 0x49, 0xa0, 0x64, 0xd8, 0x19,
|
0x75, 0x6f, 0xb4, 0x43, 0x47, 0x90, 0x19, 0x39, 0x2e, 0x09, 0xd4, 0x14, 0xaf, 0x21, 0x4a, 0x28,
|
||||||
0xa2, 0x94, 0xd2, 0x1d, 0x97, 0xb4, 0xbd, 0x31, 0x8d, 0x4f, 0x91, 0xc3, 0x6a, 0xe7, 0x50, 0x62,
|
0xdd, 0x71, 0x49, 0xcb, 0x1b, 0xd1, 0xa8, 0x8a, 0x02, 0x56, 0x3d, 0x83, 0x22, 0x0f, 0x78, 0x36,
|
||||||
0x01, 0xcf, 0x67, 0xb6, 0x15, 0x92, 0x1f, 0x2c, 0xec, 0x5f, 0x45, 0x90, 0x12, 0xcf, 0xfa, 0xd0,
|
0xb5, 0xad, 0x90, 0xfc, 0x68, 0x61, 0xaf, 0x64, 0xc8, 0xc7, 0x9e, 0x55, 0xd1, 0xa5, 0x44, 0xd1,
|
||||||
0x85, 0xd4, 0xa1, 0x1f, 0xc7, 0xfd, 0x80, 0x57, 0xf7, 0xc1, 0xcd, 0x78, 0xa9, 0x86, 0x80, 0x40,
|
0x0f, 0xa3, 0x79, 0x20, 0xba, 0x7b, 0xef, 0x76, 0xbc, 0xc4, 0x40, 0x40, 0x20, 0x07, 0xce, 0xd7,
|
||||||
0x0c, 0x9c, 0xaf, 0x09, 0xab, 0xa7, 0x2c, 0x66, 0x63, 0xa4, 0x41, 0xe9, 0x7a, 0x11, 0xed, 0xe2,
|
0x84, 0xf7, 0x53, 0x1a, 0xf3, 0x35, 0xd2, 0xa1, 0x78, 0xb3, 0x89, 0xb6, 0x71, 0xd2, 0x84, 0x3e,
|
||||||
0xb4, 0x09, 0x7d, 0x00, 0x30, 0xa5, 0xb6, 0x33, 0x76, 0x88, 0x6d, 0x06, 0x4c, 0x00, 0x59, 0x5c,
|
0x00, 0x98, 0x50, 0xdb, 0x19, 0x39, 0xc4, 0x36, 0x03, 0x2e, 0x80, 0x34, 0x2e, 0xc4, 0x96, 0x1e,
|
||||||
0x4c, 0x2c, 0x7d, 0xa4, 0x44, 0x72, 0x8f, 0x4a, 0xc8, 0x8e, 0x6b, 0x25, 0x99, 0x46, 0x1e, 0xc7,
|
0x52, 0x99, 0xdc, 0x59, 0x0b, 0xd9, 0x51, 0xaf, 0xc4, 0x5b, 0x74, 0x00, 0x39, 0xc7, 0xbb, 0xb0,
|
||||||
0xbb, 0xb4, 0x5c, 0x27, 0xa9, 0x90, 0x64, 0x1a, 0x75, 0x3d, 0x8f, 0x6e, 0x15, 0xaf, 0xc4, 0x00,
|
0x5c, 0x27, 0xea, 0x90, 0xfa, 0xce, 0xf5, 0x55, 0x05, 0xb0, 0x75, 0xd9, 0x12, 0x56, 0x1c, 0xbb,
|
||||||
0xbb, 0x1e, 0x4d, 0x17, 0xee, 0x23, 0x28, 0x24, 0x5d, 0x31, 0x3a, 0xcf, 0xad, 0x4a, 0x7a, 0x4a,
|
0xd9, 0x14, 0xf4, 0xe8, 0x46, 0x33, 0xe7, 0x79, 0xa8, 0x6d, 0x8f, 0x26, 0x1b, 0xf9, 0x09, 0xe4,
|
||||||
0x46, 0x21, 0x5d, 0xf7, 0x9b, 0x18, 0x86, 0x54, 0x90, 0xd6, 0x52, 0x04, 0xf6, 0xa7, 0xeb, 0x79,
|
0xe2, 0x29, 0xc9, 0xea, 0xbb, 0xd1, 0x59, 0xcf, 0xc9, 0x30, 0xa4, 0xab, 0xf9, 0x13, 0xc1, 0x90,
|
||||||
0xd4, 0x8b, 0xd7, 0x79, 0x78, 0x81, 0x52, 0xd2, 0x84, 0xa3, 0x1c, 0x5e, 0xa7, 0x66, 0x44, 0xdb,
|
0x06, 0xf9, 0x95, 0x34, 0x81, 0xff, 0xf3, 0xd5, 0x9e, 0xcd, 0xe6, 0x55, 0x5e, 0x5e, 0xa0, 0x16,
|
||||||
0x6d, 0x00, 0xc3, 0x85, 0x52, 0x66, 0x5a, 0x7c, 0x2f, 0xd1, 0x62, 0xff, 0x82, 0xfa, 0x61, 0xbb,
|
0x75, 0xe9, 0x20, 0x83, 0x57, 0xa9, 0xb6, 0xd9, 0x75, 0x6b, 0xc0, 0x60, 0xae, 0x96, 0xb8, 0x36,
|
||||||
0xb5, 0x59, 0xd1, 0x58, 0xa0, 0x87, 0x00, 0x43, 0x97, 0x8e, 0x9e, 0x9b, 0x8c, 0xd6, 0xdd, 0x28,
|
0xdf, 0x8b, 0xb5, 0xd9, 0x3b, 0xa7, 0x7e, 0xd8, 0x6a, 0xae, 0x4f, 0xd4, 0xe7, 0xe8, 0x31, 0xc0,
|
||||||
0x62, 0x43, 0xbe, 0x7a, 0x5d, 0x2d, 0x63, 0xeb, 0x45, 0x23, 0x72, 0xf4, 0x9d, 0xaf, 0x09, 0x2e,
|
0xc0, 0xa5, 0xc3, 0x97, 0x26, 0xa7, 0x79, 0x9b, 0x45, 0xac, 0x2b, 0xd7, 0x57, 0x95, 0x12, 0xb6,
|
||||||
0x0e, 0x93, 0x21, 0xfa, 0x09, 0xe4, 0x99, 0x3d, 0x69, 0x0d, 0xb7, 0x36, 0x09, 0x31, 0x7b, 0x4a,
|
0x2e, 0xeb, 0xcc, 0xd1, 0x73, 0xbe, 0x26, 0xb8, 0x30, 0x88, 0x97, 0xe8, 0x67, 0x90, 0xe5, 0xf6,
|
||||||
0x00, 0x31, 0x30, 0xe2, 0x2a, 0x58, 0x4c, 0x5d, 0xc7, 0x7b, 0x6e, 0x86, 0x96, 0x3f, 0x21, 0xa1,
|
0x78, 0x54, 0xdc, 0x59, 0x27, 0xc4, 0xed, 0x09, 0x41, 0x44, 0x40, 0xc6, 0x55, 0x30, 0x9f, 0xb8,
|
||||||
0xb2, 0xcf, 0x6f, 0x88, 0xd8, 0x3a, 0x60, 0xc6, 0x5f, 0x8a, 0x7f, 0xfa, 0xa6, 0xba, 0x53, 0xf3,
|
0x8e, 0xf7, 0xd2, 0x0c, 0x2d, 0x7f, 0x4c, 0x42, 0x75, 0x57, 0xbc, 0x18, 0x91, 0xb5, 0xcf, 0x8d,
|
||||||
0xa0, 0xb8, 0x8e, 0x13, 0x69, 0x90, 0x8e, 0xc7, 0x01, 0x09, 0x99, 0x60, 0xb2, 0x38, 0x9e, 0xad,
|
0xac, 0xae, 0x2e, 0x1d, 0x5a, 0xae, 0x39, 0x72, 0xad, 0x71, 0xa0, 0x7e, 0x9f, 0xe3, 0x85, 0x05,
|
||||||
0x65, 0x90, 0x61, 0x0c, 0x70, 0x19, 0x20, 0x10, 0x2f, 0xac, 0xe0, 0x82, 0x49, 0xa3, 0x8c, 0xd9,
|
0x6e, 0x3b, 0x66, 0xa6, 0x5f, 0xcb, 0x7f, 0xf9, 0xa6, 0xb2, 0x55, 0xf5, 0xa0, 0xb0, 0xba, 0x89,
|
||||||
0x38, 0x2a, 0xfc, 0x17, 0xc4, 0x7a, 0x6e, 0x32, 0x07, 0x17, 0x86, 0x14, 0x19, 0x1e, 0x5b, 0xc1,
|
0xa9, 0x96, 0x8e, 0x46, 0x01, 0x09, 0xb9, 0xc4, 0xd2, 0x38, 0xda, 0xad, 0x84, 0x93, 0xe2, 0x1c,
|
||||||
0x45, 0xbc, 0xdf, 0xaf, 0x21, 0xcf, 0x0f, 0x02, 0x7d, 0x0e, 0xd2, 0x88, 0xce, 0xbd, 0x70, 0x73,
|
0x09, 0xe1, 0x20, 0x90, 0xcf, 0xad, 0xe0, 0x9c, 0x8b, 0xa9, 0x84, 0xf9, 0x9a, 0x8d, 0x8a, 0x4b,
|
||||||
0x39, 0xec, 0xa7, 0x7b, 0x0b, 0xf3, 0xc4, 0x99, 0xad, 0x81, 0xb5, 0x53, 0x28, 0xc4, 0x2e, 0x74,
|
0x62, 0xbd, 0x34, 0xb9, 0x43, 0x48, 0x29, 0xcf, 0x0c, 0x4f, 0xad, 0xe0, 0x3c, 0xba, 0xef, 0xb7,
|
||||||
0x7f, 0xdd, 0xf8, 0xc4, 0xc6, 0x9d, 0x6b, 0x9c, 0x6f, 0xdf, 0x16, 0x97, 0x96, 0x3b, 0xe7, 0x3f,
|
0x90, 0x15, 0xa5, 0x42, 0x9f, 0x43, 0x7e, 0x48, 0x67, 0x5e, 0xb8, 0x7e, 0x4e, 0x76, 0x93, 0xd3,
|
||||||
0x2f, 0x62, 0x3e, 0xa9, 0xfd, 0x4d, 0x80, 0x02, 0x8e, 0xce, 0x39, 0x08, 0x53, 0xf7, 0x4c, 0x6e,
|
0x88, 0x7b, 0xa2, 0xdc, 0x57, 0xc0, 0xea, 0x31, 0xe4, 0x22, 0x17, 0x7a, 0xb8, 0x1a, 0x95, 0x72,
|
||||||
0xeb, 0x9e, 0xd9, 0x54, 0x64, 0x66, 0xab, 0x22, 0x93, 0xa2, 0xca, 0xa6, 0x8a, 0x6a, 0xc3, 0x9c,
|
0xfd, 0xde, 0x8d, 0xaa, 0x6c, 0xbe, 0x2f, 0x17, 0x96, 0x3b, 0x13, 0x7f, 0x5e, 0xc6, 0x62, 0x53,
|
||||||
0xf8, 0x46, 0xe6, 0x72, 0x6f, 0x60, 0x2e, 0x9f, 0x62, 0xee, 0x3e, 0xec, 0x8d, 0x7d, 0x3a, 0x65,
|
0xfd, 0xbb, 0x04, 0x39, 0xcc, 0x94, 0x10, 0x84, 0x89, 0x97, 0x29, 0xb3, 0xf1, 0x32, 0xad, 0x7b,
|
||||||
0x37, 0x09, 0xf5, 0x2d, 0x7f, 0x11, 0x17, 0xc0, 0x6e, 0x64, 0x1d, 0x24, 0xc6, 0x6d, 0x82, 0xa5,
|
0x38, 0xb5, 0xd1, 0xc3, 0x71, 0x1b, 0xa6, 0x13, 0x6d, 0xb8, 0x66, 0x4e, 0x7e, 0x23, 0x73, 0x99,
|
||||||
0x6d, 0x82, 0x6b, 0x26, 0x48, 0x98, 0x04, 0x33, 0xea, 0x05, 0xe4, 0xad, 0x39, 0x21, 0x10, 0x6d,
|
0x37, 0x30, 0x97, 0x4d, 0x30, 0xf7, 0x10, 0x76, 0x46, 0x3e, 0x9d, 0xf0, 0xb7, 0x87, 0xfa, 0x96,
|
||||||
0x2b, 0xb4, 0x58, 0x46, 0x65, 0xcc, 0xc6, 0xe8, 0x01, 0x88, 0x23, 0x6a, 0xf3, 0x7c, 0xf6, 0xd2,
|
0x3f, 0x8f, 0x06, 0xe5, 0x36, 0xb3, 0xf6, 0x63, 0xe3, 0x26, 0xc1, 0xf9, 0x4d, 0x82, 0xab, 0x26,
|
||||||
0x02, 0xd3, 0x7d, 0x9f, 0xfa, 0x4d, 0x6a, 0x13, 0xcc, 0x00, 0xb5, 0x19, 0xc8, 0x2d, 0xfa, 0xc2,
|
0xe4, 0x31, 0x09, 0xa6, 0xd4, 0x0b, 0xc8, 0x5b, 0x73, 0x42, 0x20, 0xdb, 0x56, 0x68, 0xf1, 0x8c,
|
||||||
0x73, 0xa9, 0x65, 0xf7, 0x7c, 0x3a, 0x89, 0xda, 0xfd, 0x5b, 0xdb, 0x56, 0x0b, 0x0a, 0x73, 0xd6,
|
0x4a, 0x98, 0xaf, 0xd1, 0x23, 0x90, 0x87, 0xd4, 0x16, 0xf9, 0xec, 0x24, 0x25, 0x68, 0xf8, 0x3e,
|
||||||
0xd8, 0x92, 0xc6, 0x75, 0x6f, 0xbb, 0xd1, 0x5c, 0x0f, 0xc4, 0xbb, 0x60, 0x52, 0x9d, 0xf1, 0xd2,
|
0xf5, 0x1b, 0xd4, 0x26, 0x98, 0x03, 0xaa, 0x53, 0x50, 0x9a, 0xf4, 0xd2, 0x73, 0xa9, 0x65, 0x77,
|
||||||
0xda, 0x3f, 0x04, 0x50, 0xdf, 0x8e, 0x46, 0x6d, 0x28, 0x71, 0xa4, 0x99, 0x7a, 0xe1, 0x1c, 0xbd,
|
0x7d, 0x3a, 0x66, 0x0f, 0xc4, 0x5b, 0x07, 0x5d, 0x13, 0x72, 0x33, 0x3e, 0x0a, 0xe3, 0x51, 0xf7,
|
||||||
0xcb, 0x46, 0xac, 0xc7, 0xc1, 0x7c, 0x3d, 0x7e, 0xe3, 0xf5, 0x98, 0xea, 0x26, 0xd9, 0x77, 0xeb,
|
0x60, 0x73, 0x34, 0xdd, 0x0c, 0x24, 0xe6, 0x66, 0xdc, 0xbf, 0xd1, 0xd1, 0xea, 0x3f, 0x25, 0xd0,
|
||||||
0x26, 0x0f, 0x60, 0x97, 0x97, 0x77, 0xf2, 0x18, 0x10, 0xb5, 0xec, 0x51, 0xae, 0x91, 0x91, 0x77,
|
0xde, 0x8e, 0x46, 0x2d, 0x28, 0x0a, 0xa4, 0x99, 0xf8, 0x26, 0x3a, 0x78, 0x97, 0x8b, 0xf8, 0x54,
|
||||||
0x70, 0x79, 0xc8, 0xcb, 0x8c, 0xd9, 0x6b, 0x79, 0x10, 0x7b, 0x8e, 0x37, 0xa9, 0x55, 0x21, 0xd7,
|
0x84, 0xd9, 0x6a, 0xfd, 0xc6, 0x07, 0x35, 0x31, 0x6f, 0xd2, 0xef, 0x36, 0x6f, 0x1e, 0xc1, 0xb6,
|
||||||
0x74, 0x29, 0x3b, 0xb0, 0xbc, 0x4f, 0xac, 0x80, 0x7a, 0x09, 0x8f, 0x7c, 0x76, 0xfc, 0xf7, 0x0c,
|
0x18, 0x00, 0xf1, 0xe7, 0x83, 0xac, 0xa7, 0x0f, 0x32, 0xf5, 0x94, 0xb2, 0x85, 0x4b, 0x03, 0xd1,
|
||||||
0x94, 0x52, 0x0f, 0x35, 0xf4, 0x08, 0xf6, 0x9a, 0x9d, 0xf3, 0xfe, 0x40, 0xc7, 0x66, 0xb3, 0x6b,
|
0x66, 0xdc, 0x5e, 0xcd, 0x82, 0xdc, 0x75, 0xbc, 0x71, 0xb5, 0x02, 0x99, 0x86, 0x4b, 0x79, 0xc1,
|
||||||
0x9c, 0xb6, 0xcf, 0xe4, 0x1d, 0xf5, 0x70, 0xb9, 0xd2, 0x94, 0xe9, 0x06, 0xb4, 0xfd, 0x06, 0xab,
|
0xb2, 0x3e, 0xb1, 0x02, 0xea, 0xc5, 0x3c, 0x8a, 0xdd, 0xe1, 0x3f, 0x52, 0x50, 0x4c, 0x7c, 0xda,
|
||||||
0x42, 0xae, 0x6d, 0xb4, 0xf4, 0xdf, 0xcb, 0x82, 0x7a, 0x7b, 0xb9, 0xd2, 0xe4, 0x14, 0x90, 0x5f,
|
0xa1, 0x27, 0xb0, 0xd3, 0x38, 0x3d, 0xeb, 0xf5, 0x0d, 0x6c, 0x36, 0x3a, 0xed, 0xe3, 0xd6, 0x89,
|
||||||
0x68, 0x9f, 0x40, 0x99, 0x01, 0xcc, 0xf3, 0x5e, 0xab, 0x3e, 0xd0, 0xe5, 0x8c, 0xaa, 0x2e, 0x57,
|
0xb2, 0xa5, 0xed, 0x2f, 0x96, 0xba, 0x3a, 0x59, 0x83, 0x36, 0xbf, 0xda, 0x2a, 0x90, 0x69, 0xb5,
|
||||||
0xda, 0xc1, 0x75, 0x5c, 0xcc, 0xf9, 0x87, 0x50, 0xc0, 0xfa, 0xef, 0xce, 0xf5, 0xfe, 0x40, 0xce,
|
0x9b, 0xc6, 0x1f, 0x15, 0x49, 0xbb, 0xbb, 0x58, 0xea, 0x4a, 0x02, 0x28, 0x9e, 0xc0, 0x4f, 0xa0,
|
||||||
0xaa, 0x07, 0xcb, 0x95, 0x86, 0x52, 0xc0, 0xa4, 0xa4, 0xee, 0x83, 0x84, 0xf5, 0x7e, 0xaf, 0x6b,
|
0xc4, 0x01, 0xe6, 0x59, 0xb7, 0x59, 0xeb, 0x1b, 0x4a, 0x4a, 0xd3, 0x16, 0x4b, 0x7d, 0xef, 0x26,
|
||||||
0xf4, 0x75, 0x59, 0x54, 0x7f, 0xb4, 0x5c, 0x69, 0xb7, 0xb6, 0x50, 0xb1, 0x4a, 0x7f, 0x06, 0xfb,
|
0x2e, 0xe2, 0xfc, 0x43, 0xc8, 0x61, 0xe3, 0x0f, 0x67, 0x46, 0xaf, 0xaf, 0xa4, 0xb5, 0xbd, 0xc5,
|
||||||
0xad, 0xee, 0x97, 0x46, 0xa7, 0x5b, 0x6f, 0x99, 0x3d, 0xdc, 0x3d, 0xc3, 0x7a, 0xbf, 0x2f, 0xe7,
|
0x52, 0x47, 0x09, 0x60, 0xdc, 0x52, 0x0f, 0x21, 0x8f, 0x8d, 0x5e, 0xb7, 0xd3, 0xee, 0x19, 0x8a,
|
||||||
0xd4, 0xea, 0x72, 0xa5, 0xbd, 0x9f, 0xc2, 0xdf, 0x10, 0xdd, 0x07, 0x20, 0xf6, 0xda, 0xc6, 0x99,
|
0xac, 0xfd, 0x64, 0xb1, 0xd4, 0xef, 0x6c, 0xa0, 0x22, 0x95, 0xfe, 0x02, 0x76, 0x9b, 0x9d, 0x2f,
|
||||||
0x9c, 0x57, 0x6f, 0x2d, 0x57, 0xda, 0x7b, 0x29, 0x68, 0x44, 0x6a, 0x94, 0x71, 0xb3, 0xd3, 0xed,
|
0xdb, 0xa7, 0x9d, 0x5a, 0xd3, 0xec, 0xe2, 0xce, 0x09, 0x36, 0x7a, 0x3d, 0x25, 0xa3, 0x55, 0x16,
|
||||||
0xeb, 0x72, 0xe1, 0x46, 0xc6, 0x8c, 0xec, 0xe3, 0x3f, 0x00, 0xba, 0xf9, 0x94, 0x45, 0xf7, 0x40,
|
0x4b, 0xfd, 0xfd, 0x04, 0xfe, 0x96, 0xe8, 0x3e, 0x00, 0xb9, 0xdb, 0x6a, 0x9f, 0x28, 0x59, 0xed,
|
||||||
0x34, 0xba, 0x86, 0x2e, 0xef, 0xf0, 0xfc, 0x6f, 0x22, 0x0c, 0xea, 0x11, 0x54, 0x83, 0x6c, 0xe7,
|
0xce, 0x62, 0xa9, 0xbf, 0x97, 0x80, 0x32, 0x52, 0x59, 0xc6, 0x8d, 0xd3, 0x4e, 0xcf, 0x50, 0x72,
|
||||||
0xab, 0x2f, 0x64, 0x41, 0xfd, 0xf1, 0x72, 0xa5, 0xdd, 0xb9, 0x09, 0xea, 0x7c, 0xf5, 0xc5, 0x31,
|
0xb7, 0x32, 0xe6, 0x64, 0x1f, 0xfe, 0x09, 0xd0, 0xed, 0x8f, 0x5f, 0xf4, 0x00, 0xe4, 0x76, 0xa7,
|
||||||
0x85, 0x52, 0x3a, 0x70, 0x0d, 0xa4, 0x27, 0xfa, 0xa0, 0xde, 0xaa, 0x0f, 0xea, 0xf2, 0x0e, 0xff,
|
0x6d, 0x28, 0x5b, 0x22, 0xff, 0xdb, 0x88, 0x36, 0xf5, 0x08, 0xaa, 0x42, 0xfa, 0xf4, 0xab, 0x2f,
|
||||||
0xa5, 0xc4, 0xfd, 0x84, 0x84, 0x16, 0x2b, 0xc2, 0x43, 0xc8, 0x19, 0xfa, 0x53, 0x1d, 0xcb, 0x82,
|
0x14, 0x49, 0xfb, 0xe9, 0x62, 0xa9, 0xdf, 0xbb, 0x0d, 0x3a, 0xfd, 0xea, 0x8b, 0x43, 0x0a, 0xc5,
|
||||||
0xba, 0xbf, 0x5c, 0x69, 0xbb, 0x09, 0xc0, 0x20, 0x97, 0xc4, 0x47, 0x15, 0xc8, 0xd7, 0x3b, 0x5f,
|
0x64, 0xe0, 0x2a, 0xe4, 0x9f, 0x19, 0xfd, 0x5a, 0xb3, 0xd6, 0xaf, 0x29, 0x5b, 0xe2, 0x2f, 0xc5,
|
||||||
0xd6, 0x9f, 0xf5, 0xe5, 0x8c, 0x8a, 0x96, 0x2b, 0x6d, 0x2f, 0x71, 0xd7, 0xdd, 0x17, 0xd6, 0x22,
|
0xee, 0x67, 0x24, 0xb4, 0x78, 0x13, 0xee, 0x43, 0xa6, 0x6d, 0x3c, 0x37, 0xb0, 0x22, 0x69, 0xbb,
|
||||||
0x38, 0xfe, 0x9f, 0x00, 0xe5, 0xf4, 0xf5, 0x8d, 0x2a, 0x20, 0x9e, 0xb6, 0x3b, 0x7a, 0xb2, 0x5d,
|
0x8b, 0xa5, 0xbe, 0x1d, 0x03, 0xda, 0xe4, 0x82, 0xf8, 0xa8, 0x0c, 0xd9, 0xda, 0xe9, 0x97, 0xb5,
|
||||||
0xda, 0x17, 0x8d, 0xd1, 0x11, 0x14, 0x5b, 0x6d, 0xac, 0x37, 0x07, 0x5d, 0xfc, 0x2c, 0xc9, 0x25,
|
0x17, 0x3d, 0x25, 0xa5, 0xa1, 0xc5, 0x52, 0xdf, 0x89, 0xdd, 0x35, 0xf7, 0xd2, 0x9a, 0x07, 0x87,
|
||||||
0x0d, 0x6a, 0x39, 0x3e, 0x13, 0xf8, 0x02, 0xfd, 0x02, 0xca, 0xfd, 0x67, 0x4f, 0x3a, 0x6d, 0xe3,
|
0xff, 0x93, 0xa0, 0x94, 0x7c, 0xf0, 0x51, 0x19, 0xe4, 0xe3, 0xd6, 0xa9, 0x11, 0x5f, 0x97, 0xf4,
|
||||||
0xb7, 0x26, 0x8b, 0x98, 0x51, 0x1f, 0x2c, 0x57, 0xda, 0xdd, 0x2d, 0x30, 0x99, 0xf9, 0x64, 0x64,
|
0xb1, 0x35, 0x3a, 0x80, 0x42, 0xb3, 0x85, 0x8d, 0x46, 0xbf, 0x83, 0x5f, 0xc4, 0xb9, 0x24, 0x41,
|
||||||
0x85, 0xc4, 0xee, 0xf3, 0x1b, 0x26, 0x72, 0x4a, 0x02, 0x6a, 0xc2, 0x7e, 0xb2, 0x74, 0xb3, 0x59,
|
0x4d, 0xc7, 0xe7, 0x02, 0x9f, 0xa3, 0x5f, 0x41, 0xa9, 0xf7, 0xe2, 0xd9, 0x69, 0xab, 0xfd, 0x7b,
|
||||||
0x56, 0xfd, 0x64, 0xb9, 0xd2, 0x3e, 0xfa, 0xde, 0xf5, 0xeb, 0xdd, 0x25, 0x01, 0xdd, 0x83, 0x42,
|
0x93, 0x47, 0x4c, 0x69, 0x8f, 0x16, 0x4b, 0xfd, 0xfe, 0x06, 0x98, 0x4c, 0x7d, 0x32, 0xb4, 0x42,
|
||||||
0x1c, 0x24, 0x51, 0x52, 0x7a, 0x69, 0xbc, 0xe0, 0xf8, 0x2f, 0x02, 0x14, 0xd7, 0xed, 0x2a, 0x22,
|
0x62, 0xf7, 0xc4, 0x1b, 0xc4, 0x9c, 0x79, 0x09, 0x35, 0x60, 0x37, 0x3e, 0xba, 0xbe, 0x2c, 0xad,
|
||||||
0xdc, 0xe8, 0x9a, 0x3a, 0xc6, 0x5d, 0x9c, 0x30, 0xb0, 0x76, 0x1a, 0x94, 0x0d, 0xd1, 0x5d, 0x28,
|
0x7d, 0xb2, 0x58, 0xea, 0x1f, 0xfd, 0xe0, 0xf9, 0xd5, 0xed, 0x79, 0x09, 0x3d, 0x80, 0x5c, 0x14,
|
||||||
0x9c, 0xe9, 0x86, 0x8e, 0xdb, 0xcd, 0xa4, 0x30, 0xd6, 0x90, 0x33, 0xe2, 0x11, 0xdf, 0x19, 0xa1,
|
0x24, 0x56, 0x52, 0xf2, 0x68, 0x74, 0xe0, 0xf0, 0x6f, 0x12, 0x14, 0x56, 0xe3, 0x8a, 0x11, 0xde,
|
||||||
0x8f, 0xa1, 0x6c, 0x74, 0xcd, 0xfe, 0x79, 0xf3, 0x71, 0x92, 0x3a, 0xdb, 0x3f, 0x15, 0xaa, 0x3f,
|
0xee, 0x98, 0x06, 0xc6, 0x1d, 0x1c, 0x33, 0xb0, 0x72, 0xb6, 0x29, 0x5f, 0xa2, 0xfb, 0x90, 0x3b,
|
||||||
0x1f, 0x5d, 0x30, 0x3e, 0x8f, 0xa3, 0x1a, 0x7a, 0x5a, 0xef, 0xb4, 0x5b, 0x1c, 0x9a, 0x55, 0x95,
|
0x31, 0xda, 0x06, 0x6e, 0x35, 0xe2, 0xc6, 0x58, 0x41, 0x4e, 0x88, 0x47, 0x7c, 0x67, 0x88, 0x3e,
|
||||||
0xe5, 0x4a, 0xbb, 0xbd, 0x86, 0xb6, 0xf9, 0x3b, 0x26, 0xc2, 0x1e, 0xdb, 0x50, 0xf9, 0xfe, 0xc6,
|
0x86, 0x52, 0xbb, 0x63, 0xf6, 0xce, 0x1a, 0x4f, 0xe3, 0xd4, 0xf9, 0xfd, 0x89, 0x50, 0xbd, 0xd9,
|
||||||
0x84, 0x34, 0xc8, 0xd7, 0x7b, 0x3d, 0xdd, 0x68, 0x25, 0x7f, 0xbf, 0xf1, 0xd5, 0x67, 0x33, 0xe2,
|
0xf0, 0x9c, 0xf3, 0x79, 0xc8, 0x7a, 0xe8, 0x79, 0xed, 0xb4, 0xd5, 0x14, 0xd0, 0xb4, 0xa6, 0x2e,
|
||||||
0xd9, 0x11, 0xe2, 0xb4, 0x8b, 0xcf, 0xf4, 0x41, 0xf2, 0xf3, 0x1b, 0xc4, 0x29, 0x8d, 0xae, 0xf7,
|
0x96, 0xfa, 0xdd, 0x15, 0x34, 0xfa, 0xe4, 0x61, 0xd8, 0x43, 0x1b, 0xca, 0x3f, 0x3c, 0x98, 0x90,
|
||||||
0xc6, 0xe1, 0xab, 0xef, 0x2a, 0x3b, 0xdf, 0x7e, 0x57, 0xd9, 0x79, 0x75, 0x55, 0x11, 0xbe, 0xbd,
|
0x0e, 0xd9, 0x5a, 0xb7, 0x6b, 0xb4, 0x9b, 0xf1, 0xbf, 0x5f, 0xfb, 0x6a, 0xd3, 0x29, 0xf1, 0x6c,
|
||||||
0xaa, 0x08, 0xff, 0xba, 0xaa, 0xec, 0xfc, 0xe7, 0xaa, 0x22, 0x7c, 0xf3, 0xef, 0x8a, 0x30, 0xcc,
|
0x86, 0x38, 0xee, 0xe0, 0x13, 0xa3, 0x1f, 0xff, 0xf9, 0x35, 0xe2, 0x98, 0xb2, 0x0f, 0x80, 0xfa,
|
||||||
0xb3, 0x46, 0xf6, 0xf9, 0xff, 0x03, 0x00, 0x00, 0xff, 0xff, 0xe5, 0x17, 0x2b, 0x62, 0xdd, 0x0e,
|
0xfe, 0xeb, 0xef, 0xca, 0x5b, 0xdf, 0x7e, 0x57, 0xde, 0x7a, 0x7d, 0x5d, 0x96, 0xbe, 0xbd, 0x2e,
|
||||||
0x00, 0x00,
|
0x4b, 0xff, 0xbe, 0x2e, 0x6f, 0x7d, 0x7f, 0x5d, 0x96, 0xbe, 0xf9, 0x4f, 0x59, 0x1a, 0x64, 0xf9,
|
||||||
|
0x20, 0xfb, 0xfc, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0xd8, 0x41, 0xd9, 0x3a, 0x0f, 0x0f, 0x00,
|
||||||
|
0x00,
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,14 +101,19 @@ message FileInfo {
|
||||||
int32 modified_ns = 11;
|
int32 modified_ns = 11;
|
||||||
uint64 modified_by = 12 [(gogoproto.customtype) = "ShortID", (gogoproto.nullable) = false];
|
uint64 modified_by = 12 [(gogoproto.customtype) = "ShortID", (gogoproto.nullable) = false];
|
||||||
bool deleted = 6;
|
bool deleted = 6;
|
||||||
bool invalid = 7;
|
bool invalid = 7 [(gogoproto.customname) = "RawInvalid"];
|
||||||
bool no_permissions = 8;
|
bool no_permissions = 8;
|
||||||
Vector version = 9 [(gogoproto.nullable) = false];
|
Vector version = 9 [(gogoproto.nullable) = false];
|
||||||
int64 sequence = 10;
|
int64 sequence = 10;
|
||||||
int32 block_size = 13 [(gogoproto.customname) = "RawBlockSize"];
|
int32 block_size = 13 [(gogoproto.customname) = "RawBlockSize"];
|
||||||
|
|
||||||
repeated BlockInfo Blocks = 16 [(gogoproto.nullable) = false];
|
repeated BlockInfo Blocks = 16 [(gogoproto.nullable) = false];
|
||||||
string symlink_target = 17;
|
string symlink_target = 17;
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
uint32 local_flags = 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum FileInfoType {
|
enum FileInfoType {
|
||||||
|
|
|
@ -28,14 +28,14 @@ func (m Hello) Magic() uint32 {
|
||||||
func (f FileInfo) String() string {
|
func (f FileInfo) String() string {
|
||||||
switch f.Type {
|
switch f.Type {
|
||||||
case FileInfoTypeDirectory:
|
case FileInfoTypeDirectory:
|
||||||
return fmt.Sprintf("Directory{Name:%q, Sequence:%d, Permissions:0%o, ModTime:%v, Version:%v, Deleted:%v, Invalid:%v, NoPermissions:%v}",
|
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.Invalid, f.NoPermissions)
|
f.Name, f.Sequence, f.Permissions, f.ModTime(), f.Version, f.Deleted, f.RawInvalid, f.LocalFlags, f.NoPermissions)
|
||||||
case FileInfoTypeFile:
|
case FileInfoTypeFile:
|
||||||
return fmt.Sprintf("File{Name:%q, Sequence:%d, Permissions:0%o, ModTime:%v, Version:%v, Length:%d, Deleted:%v, Invalid:%v, NoPermissions:%v, BlockSize:%d, Blocks:%v}",
|
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, Blocks:%v}",
|
||||||
f.Name, f.Sequence, f.Permissions, f.ModTime(), f.Version, f.Size, f.Deleted, f.Invalid, f.NoPermissions, f.RawBlockSize, f.Blocks)
|
f.Name, f.Sequence, f.Permissions, f.ModTime(), f.Version, f.Size, f.Deleted, f.RawInvalid, f.LocalFlags, f.NoPermissions, f.RawBlockSize, f.Blocks)
|
||||||
case FileInfoTypeSymlink, FileInfoTypeDeprecatedSymlinkDirectory, FileInfoTypeDeprecatedSymlinkFile:
|
case FileInfoTypeSymlink, FileInfoTypeDeprecatedSymlinkDirectory, FileInfoTypeDeprecatedSymlinkFile:
|
||||||
return fmt.Sprintf("Symlink{Name:%q, Type:%v, Sequence:%d, Version:%v, Deleted:%v, Invalid:%v, NoPermissions:%v, SymlinkTarget:%q}",
|
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.Invalid, f.NoPermissions, f.SymlinkTarget)
|
f.Name, f.Type, f.Sequence, f.Version, f.Deleted, f.RawInvalid, f.LocalFlags, f.NoPermissions, f.SymlinkTarget)
|
||||||
default:
|
default:
|
||||||
panic("mystery file type detected")
|
panic("mystery file type detected")
|
||||||
}
|
}
|
||||||
|
@ -46,13 +46,25 @@ func (f FileInfo) IsDeleted() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f FileInfo) IsInvalid() bool {
|
func (f FileInfo) IsInvalid() bool {
|
||||||
return f.Invalid
|
return f.RawInvalid || f.LocalFlags&LocalInvalidFlags != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f FileInfo) IsIgnored() bool {
|
||||||
|
return f.LocalFlags&FlagLocalIgnored != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f FileInfo) MustRescan() bool {
|
||||||
|
return f.LocalFlags&FlagLocalMustRescan != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f FileInfo) IsDirectory() bool {
|
func (f FileInfo) IsDirectory() bool {
|
||||||
return f.Type == FileInfoTypeDirectory
|
return f.Type == FileInfoTypeDirectory
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f FileInfo) ShouldConflict() bool {
|
||||||
|
return f.LocalFlags&LocalConflictFlags != 0
|
||||||
|
}
|
||||||
|
|
||||||
func (f FileInfo) IsSymlink() bool {
|
func (f FileInfo) IsSymlink() bool {
|
||||||
switch f.Type {
|
switch f.Type {
|
||||||
case FileInfoTypeSymlink, FileInfoTypeDeprecatedSymlinkDirectory, FileInfoTypeDeprecatedSymlinkFile:
|
case FileInfoTypeSymlink, FileInfoTypeDeprecatedSymlinkDirectory, FileInfoTypeDeprecatedSymlinkFile:
|
||||||
|
@ -149,7 +161,14 @@ func (f FileInfo) IsEmpty() bool {
|
||||||
// - target
|
// - target
|
||||||
// A directory does not have anything specific to check.
|
// A directory does not have anything specific to check.
|
||||||
func (f FileInfo) IsEquivalent(other FileInfo, ignorePerms bool, ignoreBlocks bool) bool {
|
func (f FileInfo) IsEquivalent(other FileInfo, ignorePerms bool, ignoreBlocks bool) bool {
|
||||||
if f.Name != other.Name || f.Type != other.Type || f.Deleted != other.Deleted || f.Invalid != other.Invalid {
|
if f.MustRescan() || other.MustRescan() {
|
||||||
|
// These are per definition not equivalent because they don't
|
||||||
|
// represent a valid state, even if both happen to have the
|
||||||
|
// MustRescan bit set.
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if f.Name != other.Name || f.Type != other.Type || f.Deleted != other.Deleted || f.IsInvalid() != other.IsInvalid() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,9 +216,23 @@ func BlocksEqual(a, b []BlockInfo) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FileInfo) Invalidate(invalidatedBy ShortID) {
|
func (f *FileInfo) SetMustRescan(by ShortID) {
|
||||||
f.Invalid = true
|
f.LocalFlags = FlagLocalMustRescan
|
||||||
f.ModifiedBy = invalidatedBy
|
f.ModifiedBy = by
|
||||||
|
f.Blocks = nil
|
||||||
|
f.Sequence = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FileInfo) SetIgnored(by ShortID) {
|
||||||
|
f.LocalFlags = FlagLocalIgnored
|
||||||
|
f.ModifiedBy = by
|
||||||
|
f.Blocks = nil
|
||||||
|
f.Sequence = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FileInfo) SetUnsupported(by ShortID) {
|
||||||
|
f.LocalFlags = FlagLocalUnsupported
|
||||||
|
f.ModifiedBy = by
|
||||||
f.Blocks = nil
|
f.Blocks = nil
|
||||||
f.Sequence = 0
|
f.Sequence = 0
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ func TestWinsConflict(t *testing.T) {
|
||||||
// The first should always win over the second
|
// The first should always win over the second
|
||||||
{{ModifiedS: 42}, {ModifiedS: 41}},
|
{{ModifiedS: 42}, {ModifiedS: 41}},
|
||||||
{{ModifiedS: 41}, {ModifiedS: 42, Deleted: true}},
|
{{ModifiedS: 41}, {ModifiedS: 42, Deleted: true}},
|
||||||
{{Deleted: true}, {ModifiedS: 10, Invalid: true}},
|
{{Deleted: true}, {ModifiedS: 10, RawInvalid: true}},
|
||||||
{{ModifiedS: 41, Version: Vector{[]Counter{{42, 2}, {43, 1}}}}, {ModifiedS: 41, Version: Vector{[]Counter{{42, 1}, {43, 2}}}}},
|
{{ModifiedS: 41, Version: Vector{[]Counter{{42, 2}, {43, 1}}}}, {ModifiedS: 41, Version: Vector{[]Counter{{42, 1}, {43, 2}}}}},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -89,6 +89,21 @@ const (
|
||||||
FlagShareBits = 0x000000ff
|
FlagShareBits = 0x000000ff
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// FileInfo.LocalFlags flags
|
||||||
|
const (
|
||||||
|
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
|
||||||
|
|
||||||
|
// Flags that should result in the Invalid bit on outgoing updates
|
||||||
|
LocalInvalidFlags = FlagLocalUnsupported | FlagLocalIgnored | FlagLocalMustRescan
|
||||||
|
|
||||||
|
// 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
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrClosed = errors.New("connection closed")
|
ErrClosed = errors.New("connection closed")
|
||||||
ErrTimeout = errors.New("read timeout")
|
ErrTimeout = errors.New("read timeout")
|
||||||
|
@ -535,7 +550,7 @@ func checkFileInfoConsistency(f FileInfo) error {
|
||||||
// Directories should have no blocks
|
// Directories should have no blocks
|
||||||
return errDirectoryHasBlocks
|
return errDirectoryHasBlocks
|
||||||
|
|
||||||
case !f.Deleted && !f.Invalid && f.Type == FileInfoTypeFile && len(f.Blocks) == 0:
|
case !f.Deleted && !f.IsInvalid() && f.Type == FileInfoTypeFile && len(f.Blocks) == 0:
|
||||||
// Non-deleted, non-invalid files should have at least one block
|
// Non-deleted, non-invalid files should have at least one block
|
||||||
return errFileHasNoBlocks
|
return errFileHasNoBlocks
|
||||||
}
|
}
|
||||||
|
|
|
@ -391,6 +391,28 @@ func BenchmarkBlockSize(b *testing.B) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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(42)
|
||||||
|
if !f.IsIgnored() || f.MustRescan() || !f.IsInvalid() {
|
||||||
|
t.Error("file should be ignored and invalid")
|
||||||
|
}
|
||||||
|
|
||||||
|
f.SetMustRescan(42)
|
||||||
|
if f.IsIgnored() || !f.MustRescan() || !f.IsInvalid() {
|
||||||
|
t.Error("file should be must-rescan and invalid")
|
||||||
|
}
|
||||||
|
|
||||||
|
f.SetUnsupported(42)
|
||||||
|
if f.IsIgnored() || f.MustRescan() || !f.IsInvalid() {
|
||||||
|
t.Error("file should be invalid")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestIsEquivalent(t *testing.T) {
|
func TestIsEquivalent(t *testing.T) {
|
||||||
b := func(v bool) *bool {
|
b := func(v bool) *bool {
|
||||||
return &v
|
return &v
|
||||||
|
@ -430,8 +452,8 @@ func TestIsEquivalent(t *testing.T) {
|
||||||
eq: false,
|
eq: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
a: FileInfo{Invalid: false},
|
a: FileInfo{RawInvalid: false},
|
||||||
b: FileInfo{Invalid: true},
|
b: FileInfo{RawInvalid: true},
|
||||||
eq: false,
|
eq: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -445,6 +467,31 @@ func TestIsEquivalent(t *testing.T) {
|
||||||
eq: false,
|
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,
|
||||||
|
},
|
||||||
|
|
||||||
// Difference in blocks is not OK
|
// Difference in blocks is not OK
|
||||||
{
|
{
|
||||||
a: FileInfo{Blocks: []BlockInfo{{Hash: []byte{1, 2, 3, 4}}}},
|
a: FileInfo{Blocks: []BlockInfo{{Hash: []byte{1, 2, 3, 4}}}},
|
||||||
|
|
|
@ -373,11 +373,12 @@ func (w *walker) walkRegular(ctx context.Context, relPath string, info fs.FileIn
|
||||||
if curFile.IsEquivalent(f, w.IgnorePerms, true) {
|
if curFile.IsEquivalent(f, w.IgnorePerms, true) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if curFile.Invalid {
|
if curFile.ShouldConflict() {
|
||||||
// We do not want to override the global version with the file we
|
// The old file was invalid for whatever reason and probably not
|
||||||
// currently have. Keeping only our local counter makes sure we are in
|
// up to date with what was out there in the cluster. Drop all
|
||||||
// conflict with any other existing versions, which will be resolved by
|
// others from the version vector to indicate that we haven't
|
||||||
// the normal pulling mechanisms.
|
// taken their version into account, and possibly cause a
|
||||||
|
// conflict.
|
||||||
f.Version = f.Version.DropOthers(w.ShortID)
|
f.Version = f.Version.DropOthers(w.ShortID)
|
||||||
}
|
}
|
||||||
l.Debugln("rescan:", curFile, info.ModTime().Unix(), info.Mode()&fs.ModePerm)
|
l.Debugln("rescan:", curFile, info.ModTime().Unix(), info.Mode()&fs.ModePerm)
|
||||||
|
@ -412,11 +413,12 @@ func (w *walker) walkDir(ctx context.Context, relPath string, info fs.FileInfo,
|
||||||
if cf.IsEquivalent(f, w.IgnorePerms, true) {
|
if cf.IsEquivalent(f, w.IgnorePerms, true) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if cf.Invalid {
|
if cf.ShouldConflict() {
|
||||||
// We do not want to override the global version with the file we
|
// The old file was invalid for whatever reason and probably not
|
||||||
// currently have. Keeping only our local counter makes sure we are in
|
// up to date with what was out there in the cluster. Drop all
|
||||||
// conflict with any other existing versions, which will be resolved by
|
// others from the version vector to indicate that we haven't
|
||||||
// the normal pulling mechanisms.
|
// taken their version into account, and possibly cause a
|
||||||
|
// conflict.
|
||||||
f.Version = f.Version.DropOthers(w.ShortID)
|
f.Version = f.Version.DropOthers(w.ShortID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -467,11 +469,12 @@ func (w *walker) walkSymlink(ctx context.Context, relPath string, dchan chan pro
|
||||||
if cf.IsEquivalent(f, w.IgnorePerms, true) {
|
if cf.IsEquivalent(f, w.IgnorePerms, true) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if cf.Invalid {
|
if cf.ShouldConflict() {
|
||||||
// We do not want to override the global version with the file we
|
// The old file was invalid for whatever reason and probably not
|
||||||
// currently have. Keeping only our local counter makes sure we are in
|
// up to date with what was out there in the cluster. Drop all
|
||||||
// conflict with any other existing versions, which will be resolved by
|
// others from the version vector to indicate that we haven't
|
||||||
// the normal pulling mechanisms.
|
// taken their version into account, and possibly cause a
|
||||||
|
// conflict.
|
||||||
f.Version = f.Version.DropOthers(w.ShortID)
|
f.Version = f.Version.DropOthers(w.ShortID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -650,7 +650,7 @@ func TestIssue4841(t *testing.T) {
|
||||||
"foo": {
|
"foo": {
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Type: protocol.FileInfoTypeFile,
|
Type: protocol.FileInfoTypeFile,
|
||||||
Invalid: true,
|
LocalFlags: protocol.FlagLocalIgnored,
|
||||||
Version: protocol.Vector{}.Update(1),
|
Version: protocol.Vector{}.Update(1),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue