mirror of
https://github.com/syncthing/syncthing.git
synced 2024-11-16 02:18:44 -07:00
lib/model: Treat failed rename like del&update (#5203)
This commit is contained in:
parent
b50d57b7fd
commit
523ac45456
@ -474,10 +474,14 @@ nextFile:
|
||||
// desired state with the delete bit set is in the deletion
|
||||
// map.
|
||||
desired := fileDeletions[candidate.Name]
|
||||
// Remove the pending deletion (as we perform it by renaming)
|
||||
delete(fileDeletions, candidate.Name)
|
||||
if err := f.renameFile(candidate, desired, fi, dbUpdateChan, scanChan); err != nil {
|
||||
// Failed to rename, try to handle files as separate
|
||||
// deletions and updates.
|
||||
break
|
||||
}
|
||||
|
||||
f.renameFile(candidate, desired, fi, dbUpdateChan, scanChan)
|
||||
// Remove the pending deletion (as we performed it by renaming)
|
||||
delete(fileDeletions, candidate.Name)
|
||||
|
||||
f.queue.Done(fileName)
|
||||
continue nextFile
|
||||
@ -812,7 +816,7 @@ func (f *sendReceiveFolder) deleteFile(file protocol.FileInfo, scanChan chan<- s
|
||||
|
||||
// renameFile attempts to rename an existing file to a destination
|
||||
// and set the right attributes on it.
|
||||
func (f *sendReceiveFolder) renameFile(cur, source, target protocol.FileInfo, dbUpdateChan chan<- dbUpdateJob, scanChan chan<- string) {
|
||||
func (f *sendReceiveFolder) renameFile(cur, source, target protocol.FileInfo, dbUpdateChan chan<- dbUpdateJob, scanChan chan<- string) error {
|
||||
// Used in the defer closure below, updated by the function body. Take
|
||||
// care not declare another err.
|
||||
var err error
|
||||
@ -851,9 +855,7 @@ func (f *sendReceiveFolder) renameFile(cur, source, target protocol.FileInfo, db
|
||||
|
||||
// Check that source is compatible with what we have in the DB
|
||||
if err = f.checkToBeDeleted(cur, scanChan); err != nil {
|
||||
err = fmt.Errorf("from %s: %s", source.Name, err.Error())
|
||||
f.newError("rename check source", target.Name, err)
|
||||
return
|
||||
return err
|
||||
}
|
||||
// Check that the target corresponds to what we have in the DB
|
||||
curTarget, ok := f.model.CurrentFolderFile(f.folderID, target.Name)
|
||||
@ -882,9 +884,7 @@ func (f *sendReceiveFolder) renameFile(cur, source, target protocol.FileInfo, db
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
err = fmt.Errorf("from %s: %s", source.Name, err.Error())
|
||||
f.newError("rename check target", target.Name, err)
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
tempName := fs.TempName(target.Name)
|
||||
@ -900,36 +900,26 @@ func (f *sendReceiveFolder) renameFile(cur, source, target protocol.FileInfo, db
|
||||
} else {
|
||||
err = osutil.TryRename(f.fs, source.Name, tempName)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
blockStatsMut.Lock()
|
||||
blockStats["total"] += len(target.Blocks)
|
||||
blockStats["renamed"] += len(target.Blocks)
|
||||
blockStatsMut.Unlock()
|
||||
|
||||
// The file was renamed, so we have handled both the necessary delete
|
||||
// of the source and the creation of the target. Fix-up the metadata,
|
||||
// update the local index of the target file and rename from temp to real name.
|
||||
|
||||
dbUpdateChan <- dbUpdateJob{source, dbUpdateDeleteFile}
|
||||
|
||||
if err = f.performFinish(nil, target, curTarget, true, tempName, dbUpdateChan, scanChan); err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// We failed the rename so we have a source file that we still need to
|
||||
// get rid of. Attempt to delete it instead so that we make *some*
|
||||
// progress. The target is unhandled.
|
||||
|
||||
err = osutil.InWritableDir(f.fs.Remove, f.fs, source.Name)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("from %s: %s", source.Name, err.Error())
|
||||
f.newError("rename delete", target.Name, err)
|
||||
return
|
||||
}
|
||||
|
||||
dbUpdateChan <- dbUpdateJob{source, dbUpdateDeleteFile}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
blockStatsMut.Lock()
|
||||
blockStats["total"] += len(target.Blocks)
|
||||
blockStats["renamed"] += len(target.Blocks)
|
||||
blockStatsMut.Unlock()
|
||||
|
||||
// The file was renamed, so we have handled both the necessary delete
|
||||
// of the source and the creation of the target temp file. Fix-up the metadata,
|
||||
// update the local index of the target file and rename from temp to real name.
|
||||
|
||||
if err = f.performFinish(nil, target, curTarget, true, tempName, dbUpdateChan, scanChan); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dbUpdateChan <- dbUpdateJob{source, dbUpdateDeleteFile}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// This is the flow of data and events here, I think...
|
||||
|
Loading…
Reference in New Issue
Block a user