Skip to content

Commit

Permalink
lib/model: Handle type changes when pulling (ref syncthing#4505 synct…
Browse files Browse the repository at this point in the history
  • Loading branch information
imsodin committed Nov 13, 2017
1 parent 2b65e10 commit 73223a4
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 19 deletions.
46 changes: 28 additions & 18 deletions lib/model/rwfolder.go
Expand Up @@ -1391,26 +1391,36 @@ func (f *sendReceiveFolder) performFinish(state *sharedPullerState) error {
// should be there, but it was removed, which is a conflict, yet
// creations always wins when competing with a deletion, so no need
// to handle that specially.
if stat.IsRegular() {
switch {
// The file reappeared from nowhere or the modification or size
// has changed, rescan.
case !state.hasCurFile || !stat.ModTime().Equal(state.curFile.ModTime()) || stat.Size() != state.curFile.Size:
fallthrough

// Permissions have changed, means the file has changed, rescan.
case !f.ignorePermissions(state.curFile) && state.curFile.HasPermissionBits() && !scanner.PermsEqual(state.curFile.Permissions, curMode):
changed := false
switch {
case !state.hasCurFile:
// The file appeared from nowhere

case stat.IsDir() != state.curFile.IsDirectory() || stat.IsSymlink() != state.curFile.IsSymlink():
// The file changed type. IsRegular is implicitly tested in the condition above
l.Debugln("file type changed but not rescanned; not finishing:", state.curFile.Name)
changed = true

case stat.IsRegular():
if !stat.ModTime().Equal(state.curFile.ModTime()) || stat.Size() != state.curFile.Size {
l.Debugln("file modified but not rescanned; not finishing:", state.curFile.Name)
// Scan() is synchronous (i.e. blocks until the scan is
// completed and returns an error), but a scan can't happen
// while we're in the puller routine. Request the scan in the
// background and it'll be handled when the current pulling
// sweep is complete. As we do retries, we'll queue the scan
// for this file up to ten times, but the last nine of those
// scans will be cheap...
go f.Scan([]string{state.curFile.Name})
return fmt.Errorf("file modified but not rescanned; will try again later")
changed = true
break
}
// check permissions
fallthrough

case stat.IsDir():
// Dirs only have perm, no modetime/size
if !f.ignorePermissions(state.curFile) && state.curFile.HasPermissionBits() && !scanner.PermsEqual(state.curFile.Permissions, curMode) {
l.Debugln("file permission modified but not rescanned; not finishing:", state.curFile.Name)
changed = true
}
}

if changed {
go f.Scan([]string{state.curFile.Name})
return fmt.Errorf("file modified but not rescanned; will try again later")
}

switch {
Expand Down
1 change: 0 additions & 1 deletion lib/scanner/walk.go
Expand Up @@ -392,7 +392,6 @@ func (w *walker) walkSymlink(ctx context.Context, relPath string, dchan chan pro
// - it wasn't deleted (because it isn't now)
// - it was a symlink
// - it wasn't invalid
// - the symlink type (file/dir) was the same
// - the target was the same
cf, ok := w.CurrentFiler.CurrentFile(relPath)
if ok && !cf.IsDeleted() && cf.IsSymlink() && !cf.IsInvalid() && cf.SymlinkTarget == target {
Expand Down

0 comments on commit 73223a4

Please sign in to comment.