mirror of
https://github.com/octoleo/syncthing.git
synced 2024-12-23 03:18:59 +00:00
This commit is contained in:
parent
cf75329067
commit
c3b5eba205
@ -64,8 +64,9 @@ var (
|
|||||||
activity = newDeviceActivity()
|
activity = newDeviceActivity()
|
||||||
errNoDevice = errors.New("peers who had this file went away, or the file has changed while syncing. will retry later")
|
errNoDevice = errors.New("peers who had this file went away, or the file has changed while syncing. will retry later")
|
||||||
errDirPrefix = "directory has been deleted on a remote device but "
|
errDirPrefix = "directory has been deleted on a remote device but "
|
||||||
errDirHasToBeScanned = errors.New(errDirPrefix + "contains unexpected files, scheduling scan")
|
errDirHasToBeScanned = errors.New(errDirPrefix + "contains changed files, scheduling scan")
|
||||||
errDirHasIgnored = errors.New(errDirPrefix + "contains ignored files (see ignore documentation for (?d) prefix)")
|
errDirHasIgnored = errors.New(errDirPrefix + "contains ignored files (see ignore documentation for (?d) prefix)")
|
||||||
|
errDirHasReceiveOnlyChanged = errors.New(errDirPrefix + "contains locally changed files")
|
||||||
errDirNotEmpty = errors.New(errDirPrefix + "is not empty; the contents are probably ignored on that remote device, but not locally")
|
errDirNotEmpty = errors.New(errDirPrefix + "is not empty; the contents are probably ignored on that remote device, but not locally")
|
||||||
errNotAvailable = errors.New("no connected device has the required version of this file")
|
errNotAvailable = errors.New("no connected device has the required version of this file")
|
||||||
errModified = errors.New("file modified but not rescanned; will try again later")
|
errModified = errors.New("file modified but not rescanned; will try again later")
|
||||||
@ -1819,32 +1820,53 @@ func (f *sendReceiveFolder) deleteDirOnDisk(dir string, snap *db.Snapshot, scanC
|
|||||||
|
|
||||||
toBeDeleted := make([]string, 0, len(files))
|
toBeDeleted := make([]string, 0, len(files))
|
||||||
|
|
||||||
hasIgnored := false
|
var hasIgnored, hasKnown, hasToBeScanned, hasReceiveOnlyChanged bool
|
||||||
hasKnown := false
|
|
||||||
hasToBeScanned := false
|
|
||||||
|
|
||||||
for _, dirFile := range files {
|
for _, dirFile := range files {
|
||||||
fullDirFile := filepath.Join(dir, dirFile)
|
fullDirFile := filepath.Join(dir, dirFile)
|
||||||
if fs.IsTemporary(dirFile) || f.ignores.Match(fullDirFile).IsDeletable() {
|
switch {
|
||||||
|
case fs.IsTemporary(dirFile) || f.ignores.Match(fullDirFile).IsDeletable():
|
||||||
toBeDeleted = append(toBeDeleted, fullDirFile)
|
toBeDeleted = append(toBeDeleted, fullDirFile)
|
||||||
} else if f.ignores != nil && f.ignores.Match(fullDirFile).IsIgnored() {
|
continue
|
||||||
|
case f.ignores != nil && f.ignores.Match(fullDirFile).IsIgnored():
|
||||||
hasIgnored = true
|
hasIgnored = true
|
||||||
} else if cf, ok := snap.Get(protocol.LocalDeviceID, fullDirFile); !ok || cf.IsDeleted() || cf.IsInvalid() {
|
continue
|
||||||
// Something appeared in the dir that we either are not aware of
|
|
||||||
// at all, that we think should be deleted or that is invalid,
|
|
||||||
// but not currently ignored -> schedule scan. The scanChan
|
|
||||||
// might be nil, in which case we trust the scanning to be
|
|
||||||
// handled later as a result of our error return.
|
|
||||||
if scanChan != nil {
|
|
||||||
scanChan <- fullDirFile
|
|
||||||
}
|
}
|
||||||
|
cf, ok := snap.Get(protocol.LocalDeviceID, fullDirFile)
|
||||||
|
switch {
|
||||||
|
case !ok || cf.IsDeleted():
|
||||||
|
// Something appeared in the dir that we either are not
|
||||||
|
// aware of at all or that we think should be deleted
|
||||||
|
// -> schedule scan.
|
||||||
|
scanChan <- fullDirFile
|
||||||
hasToBeScanned = true
|
hasToBeScanned = true
|
||||||
} else {
|
continue
|
||||||
|
case ok && f.Type == config.FolderTypeReceiveOnly && cf.IsReceiveOnlyChanged():
|
||||||
|
hasReceiveOnlyChanged = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
info, err := f.fs.Lstat(fullDirFile)
|
||||||
|
var diskFile protocol.FileInfo
|
||||||
|
if err == nil {
|
||||||
|
diskFile, err = scanner.CreateFileInfo(info, fullDirFile, f.fs)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
// Lets just assume the file has changed.
|
||||||
|
scanChan <- fullDirFile
|
||||||
|
hasToBeScanned = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !cf.IsEquivalentOptional(diskFile, f.ModTimeWindow(), f.IgnorePerms, true, protocol.LocalAllFlags) {
|
||||||
|
// File on disk changed compared to what we have in db
|
||||||
|
// -> schedule scan.
|
||||||
|
scanChan <- fullDirFile
|
||||||
|
hasToBeScanned = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
// Dir contains file that is valid according to db and
|
// Dir contains file that is valid according to db and
|
||||||
// not ignored -> something weird is going on
|
// not ignored -> something weird is going on
|
||||||
hasKnown = true
|
hasKnown = true
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if hasToBeScanned {
|
if hasToBeScanned {
|
||||||
return errDirHasToBeScanned
|
return errDirHasToBeScanned
|
||||||
@ -1852,6 +1874,9 @@ func (f *sendReceiveFolder) deleteDirOnDisk(dir string, snap *db.Snapshot, scanC
|
|||||||
if hasIgnored {
|
if hasIgnored {
|
||||||
return errDirHasIgnored
|
return errDirHasIgnored
|
||||||
}
|
}
|
||||||
|
if hasReceiveOnlyChanged {
|
||||||
|
return errDirHasReceiveOnlyChanged
|
||||||
|
}
|
||||||
if hasKnown {
|
if hasKnown {
|
||||||
return errDirNotEmpty
|
return errDirNotEmpty
|
||||||
}
|
}
|
||||||
|
@ -818,9 +818,14 @@ func TestCopyOwner(t *testing.T) {
|
|||||||
// owner/group.
|
// owner/group.
|
||||||
|
|
||||||
dbUpdateChan := make(chan dbUpdateJob, 1)
|
dbUpdateChan := make(chan dbUpdateJob, 1)
|
||||||
|
scanChan := make(chan string)
|
||||||
defer close(dbUpdateChan)
|
defer close(dbUpdateChan)
|
||||||
f.handleDir(dir, f.fset.Snapshot(), dbUpdateChan, nil)
|
f.handleDir(dir, f.fset.Snapshot(), dbUpdateChan, scanChan)
|
||||||
<-dbUpdateChan // empty the channel for later
|
select {
|
||||||
|
case <-dbUpdateChan: // empty the channel for later
|
||||||
|
case toScan := <-scanChan:
|
||||||
|
t.Fatal("Unexpected receive on scanChan:", toScan)
|
||||||
|
}
|
||||||
|
|
||||||
info, err := f.fs.Lstat("foo/bar")
|
info, err := f.fs.Lstat("foo/bar")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -874,8 +879,12 @@ func TestCopyOwner(t *testing.T) {
|
|||||||
SymlinkTarget: "over the rainbow",
|
SymlinkTarget: "over the rainbow",
|
||||||
}
|
}
|
||||||
|
|
||||||
f.handleSymlink(symlink, snap, dbUpdateChan, nil)
|
f.handleSymlink(symlink, snap, dbUpdateChan, scanChan)
|
||||||
<-dbUpdateChan
|
select {
|
||||||
|
case <-dbUpdateChan:
|
||||||
|
case toScan := <-scanChan:
|
||||||
|
t.Fatal("Unexpected receive on scanChan:", toScan)
|
||||||
|
}
|
||||||
|
|
||||||
info, err = f.fs.Lstat("foo/bar/sym")
|
info, err = f.fs.Lstat("foo/bar/sym")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user