1
0
Эх сурвалжийг харах

Fix issues with renames (fixes #1302)

Extra comments explain current issues.
Audrius Butkevicius 10 жил өмнө
parent
commit
32af626630
1 өөрчлөгдсөн 26 нэмэгдсэн , 9 устгасан
  1. 26 9
      internal/model/puller.go

+ 26 - 9
internal/model/puller.go

@@ -336,8 +336,9 @@ func (p *Puller) pullerIteration(ignores *ignore.Matcher) int {
 				df, ok := p.model.CurrentFolderFile(p.folder, file.Name)
 				// Local file can be already deleted, but with a lower version
 				// number, hence the deletion coming in again as part of
-				// WithNeed
-				if ok && !df.IsDeleted() {
+				// WithNeed, furthermore, the file can simply be of the wrong
+				// type if we haven't yet managed to pull it.
+				if ok && !df.IsDeleted() && !df.IsSymlink() && !df.IsDirectory() {
 					// Put files into buckets per first hash
 					key := string(df.Blocks[0].Hash)
 					buckets[key] = append(buckets[key], df)
@@ -345,6 +346,9 @@ func (p *Puller) pullerIteration(ignores *ignore.Matcher) int {
 			}
 		case file.IsDirectory() && !file.IsSymlink():
 			// A new or changed directory
+			if debug {
+				l.Debugln("Creating directory", file.Name)
+			}
 			p.handleDir(file)
 		default:
 			// A new or changed file or symlink. This is the only case where we
@@ -372,19 +376,25 @@ nextFile:
 
 		// Local file can be already deleted, but with a lower version
 		// number, hence the deletion coming in again as part of
-		// WithNeed
-		if !f.IsSymlink() && !f.IsDeleted() {
+		// WithNeed, furthermore, the file can simply be of the wrong type if
+		// the global index changed while we were processing this iteration.
+		if !f.IsDeleted() && !f.IsSymlink() && !f.IsDirectory() {
 			key := string(f.Blocks[0].Hash)
 			for i, candidate := range buckets[key] {
 				if scanner.BlocksEqual(candidate.Blocks, f.Blocks) {
 					// Remove the candidate from the bucket
-					l := len(buckets[key]) - 1
-					buckets[key][i] = buckets[key][l]
-					buckets[key] = buckets[key][:l]
+					lidx := len(buckets[key]) - 1
+					buckets[key][i] = buckets[key][lidx]
+					buckets[key] = buckets[key][:lidx]
+
+					// candidate is our current state of the file, where as the
+					// 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)
 
-					p.renameFile(candidate, f)
+					p.renameFile(desired, f)
 
 					p.queue.Done(fileName)
 					continue nextFile
@@ -410,11 +420,18 @@ nextFile:
 	doneWg.Wait()
 
 	for _, file := range fileDeletions {
+		if debug {
+			l.Debugln("Deleting file", file.Name)
+		}
 		p.deleteFile(file)
 	}
 
 	for i := range dirDeletions {
-		p.deleteDir(dirDeletions[len(dirDeletions)-i-1])
+		dir := dirDeletions[len(dirDeletions)-i-1]
+		if debug {
+			l.Debugln("Deleting dir", dir.Name)
+		}
+		p.deleteDir(dir)
 	}
 
 	return changed