| 
					
				 | 
			
			
				@@ -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... 
			 |