|
|
@@ -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 {
|
|
|
+ return err
|
|
|
+ }
|
|
|
|
|
|
- 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.
|
|
|
+ blockStatsMut.Lock()
|
|
|
+ blockStats["total"] += len(target.Blocks)
|
|
|
+ blockStats["renamed"] += len(target.Blocks)
|
|
|
+ blockStatsMut.Unlock()
|
|
|
|
|
|
- dbUpdateChan <- dbUpdateJob{source, dbUpdateDeleteFile}
|
|
|
+ // 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
|
|
|
- }
|
|
|
- } 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.
|
|
|
+ if err = f.performFinish(nil, target, curTarget, true, tempName, dbUpdateChan, scanChan); err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
|
|
|
- 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}
|
|
|
|
|
|
- dbUpdateChan <- dbUpdateJob{source, dbUpdateDeleteFile}
|
|
|
- }
|
|
|
+ return nil
|
|
|
}
|
|
|
|
|
|
// This is the flow of data and events here, I think...
|