mirror of
https://github.com/octoleo/syncthing.git
synced 2025-02-08 23:08:27 +00:00
GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/4317
This commit is contained in:
parent
e8ba6d4771
commit
b8c249cddc
@ -1002,27 +1002,6 @@ func (f *sendReceiveFolder) handleFile(file protocol.FileInfo, copyChan chan<- c
|
|||||||
|
|
||||||
tempName := ignore.TempName(file.Name)
|
tempName := ignore.TempName(file.Name)
|
||||||
|
|
||||||
if hasCurFile && !curFile.IsDirectory() && !curFile.IsSymlink() {
|
|
||||||
// Check that the file on disk is what we expect it to be according to
|
|
||||||
// the database. If there's a mismatch here, there might be local
|
|
||||||
// changes that we don't know about yet and we should scan before
|
|
||||||
// touching the file. If we can't stat the file we'll just pull it.
|
|
||||||
if info, err := f.fs.Lstat(file.Name); err == nil {
|
|
||||||
if !info.ModTime().Equal(curFile.ModTime()) || info.Size() != curFile.Size {
|
|
||||||
l.Debugln("file modified but not rescanned; not pulling:", file.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{file.Name})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
scanner.PopulateOffsets(file.Blocks)
|
scanner.PopulateOffsets(file.Blocks)
|
||||||
|
|
||||||
var blocks []protocol.BlockInfo
|
var blocks []protocol.BlockInfo
|
||||||
@ -1101,7 +1080,8 @@ func (f *sendReceiveFolder) handleFile(file protocol.FileInfo, copyChan chan<- c
|
|||||||
available: reused,
|
available: reused,
|
||||||
availableUpdated: time.Now(),
|
availableUpdated: time.Now(),
|
||||||
ignorePerms: f.ignorePermissions(file),
|
ignorePerms: f.ignorePermissions(file),
|
||||||
version: curFile.Version,
|
hasCurFile: hasCurFile,
|
||||||
|
curFile: curFile,
|
||||||
mut: sync.NewRWMutex(),
|
mut: sync.NewRWMutex(),
|
||||||
sparse: !f.DisableSparseFiles,
|
sparse: !f.DisableSparseFiles,
|
||||||
created: time.Now(),
|
created: time.Now(),
|
||||||
@ -1386,6 +1366,36 @@ func (f *sendReceiveFolder) performFinish(state *sharedPullerState) error {
|
|||||||
// There is an old file or directory already in place. We need to
|
// There is an old file or directory already in place. We need to
|
||||||
// handle that.
|
// handle that.
|
||||||
|
|
||||||
|
curMode := uint32(stat.Mode())
|
||||||
|
if runtime.GOOS == "windows" && osutil.IsWindowsExecutable(state.file.Name) {
|
||||||
|
curMode |= 0111
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that the file on disk is what we expect it to be according to
|
||||||
|
// the database. If there's a mismatch here, there might be local
|
||||||
|
// changes that we don't know about yet and we should scan before
|
||||||
|
// touching the file.
|
||||||
|
// There is also a case where we think the file 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.
|
||||||
|
switch {
|
||||||
|
// The file reappeared from nowhere, or mtime/size has changed, fallthrough -> 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):
|
||||||
|
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 nil
|
||||||
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case stat.IsDir() || stat.IsSymlink():
|
case stat.IsDir() || stat.IsSymlink():
|
||||||
// It's a directory or a symlink. These are not versioned or
|
// It's a directory or a symlink. These are not versioned or
|
||||||
@ -1400,13 +1410,13 @@ func (f *sendReceiveFolder) performFinish(state *sharedPullerState) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
case f.inConflict(state.version, state.file.Version):
|
case f.inConflict(state.curFile.Version, state.file.Version):
|
||||||
// The new file has been changed in conflict with the existing one. We
|
// The new file has been changed in conflict with the existing one. We
|
||||||
// should file it away as a conflict instead of just removing or
|
// should file it away as a conflict instead of just removing or
|
||||||
// archiving. Also merge with the version vector we had, to indicate
|
// archiving. Also merge with the version vector we had, to indicate
|
||||||
// we have resolved the conflict.
|
// we have resolved the conflict.
|
||||||
|
|
||||||
state.file.Version = state.file.Version.Merge(state.version)
|
state.file.Version = state.file.Version.Merge(state.curFile.Version)
|
||||||
err = osutil.InWritableDir(func(name string) error {
|
err = osutil.InWritableDir(func(name string) error {
|
||||||
return f.moveForConflict(name, state.file.ModifiedBy.String())
|
return f.moveForConflict(name, state.file.ModifiedBy.String())
|
||||||
}, f.fs, state.file.Name)
|
}, f.fs, state.file.Name)
|
||||||
|
@ -27,7 +27,8 @@ type sharedPullerState struct {
|
|||||||
realName string
|
realName string
|
||||||
reused int // Number of blocks reused from temporary file
|
reused int // Number of blocks reused from temporary file
|
||||||
ignorePerms bool
|
ignorePerms bool
|
||||||
version protocol.Vector // The current (old) version
|
hasCurFile bool // Whether curFile is set
|
||||||
|
curFile protocol.FileInfo // The file as it exists now in our database
|
||||||
sparse bool
|
sparse bool
|
||||||
created time.Time
|
created time.Time
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user