mirror of
https://github.com/octoleo/syncthing.git
synced 2025-02-02 11:58:28 +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)
|
||||
|
||||
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)
|
||||
|
||||
var blocks []protocol.BlockInfo
|
||||
@ -1101,7 +1080,8 @@ func (f *sendReceiveFolder) handleFile(file protocol.FileInfo, copyChan chan<- c
|
||||
available: reused,
|
||||
availableUpdated: time.Now(),
|
||||
ignorePerms: f.ignorePermissions(file),
|
||||
version: curFile.Version,
|
||||
hasCurFile: hasCurFile,
|
||||
curFile: curFile,
|
||||
mut: sync.NewRWMutex(),
|
||||
sparse: !f.DisableSparseFiles,
|
||||
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
|
||||
// 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 {
|
||||
case stat.IsDir() || stat.IsSymlink():
|
||||
// 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
|
||||
}
|
||||
|
||||
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
|
||||
// should file it away as a conflict instead of just removing or
|
||||
// archiving. Also merge with the version vector we had, to indicate
|
||||
// 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 {
|
||||
return f.moveForConflict(name, state.file.ModifiedBy.String())
|
||||
}, f.fs, state.file.Name)
|
||||
|
@ -27,7 +27,8 @@ type sharedPullerState struct {
|
||||
realName string
|
||||
reused int // Number of blocks reused from temporary file
|
||||
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
|
||||
created time.Time
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user