mirror of
https://github.com/syncthing/syncthing.git
synced 2024-11-16 10:28:49 -07:00
Merge pull request #2136 from calmh/noarchivedir
Clarify and correct handling of existing files/directories when pulling
This commit is contained in:
commit
50a1858367
@ -1260,34 +1260,48 @@ func (p *rwFolder) performFinish(state *sharedPullerState) error {
|
|||||||
p.virtualMtimeRepo.UpdateMtime(state.file.Name, info.ModTime(), t)
|
p.virtualMtimeRepo.UpdateMtime(state.file.Name, info.ModTime(), t)
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
if stat, err := osutil.Lstat(state.realName); err == nil {
|
||||||
if p.inConflict(state.version, state.file.Version) {
|
// There is an old file or directory already in place. We need to
|
||||||
// The new file has been changed in conflict with the existing one. We
|
// handle that.
|
||||||
// should file it away as a conflict instead of just removing or
|
|
||||||
// archiving. Also merge with the version vector we had, to indicate
|
switch {
|
||||||
// we have resolved the conflict.
|
case stat.IsDir() || stat.Mode()&os.ModeSymlink != 0:
|
||||||
state.file.Version = state.file.Version.Merge(state.version)
|
// It's a directory or a symlink. These are not versioned or
|
||||||
err = osutil.InWritableDir(moveForConflict, state.realName)
|
// archived for conflicts, only removed (which of course fails for
|
||||||
} else if p.versioner != nil {
|
// non-empty directories).
|
||||||
// If we should use versioning, let the versioner archive the old
|
|
||||||
// file before we replace it. Archiving a non-existent file is not
|
// TODO: This is the place where we want to remove temporary files
|
||||||
// an error.
|
// and future hard ignores before attempting a directory delete.
|
||||||
err = p.versioner.Archive(state.realName)
|
// Should share code with p.deletDir().
|
||||||
} else {
|
|
||||||
err = nil
|
if err = osutil.InWritableDir(osutil.Remove, state.realName); err != nil {
|
||||||
}
|
return err
|
||||||
if err != nil {
|
}
|
||||||
return err
|
|
||||||
|
case p.inConflict(state.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)
|
||||||
|
if err = osutil.InWritableDir(moveForConflict, state.realName); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
case p.versioner != nil:
|
||||||
|
// If we should use versioning, let the versioner archive the old
|
||||||
|
// file before we replace it. Archiving a non-existent file is not
|
||||||
|
// an error.
|
||||||
|
|
||||||
|
if err = p.versioner.Archive(state.realName); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the target path is a symlink or a directory, we cannot copy
|
|
||||||
// over it, hence remove it before proceeding.
|
|
||||||
stat, err := osutil.Lstat(state.realName)
|
|
||||||
if err == nil && (stat.IsDir() || stat.Mode()&os.ModeSymlink != 0) {
|
|
||||||
osutil.InWritableDir(osutil.Remove, state.realName)
|
|
||||||
}
|
|
||||||
// Replace the original content with the new one
|
// Replace the original content with the new one
|
||||||
if err = osutil.Rename(state.tempName, state.realName); err != nil {
|
if err := osutil.Rename(state.tempName, state.realName); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user