From 32af6266305913c87017535e934fb654cd9e8a09 Mon Sep 17 00:00:00 2001 From: Audrius Butkevicius Date: Fri, 30 Jan 2015 14:32:59 +0000 Subject: [PATCH] Fix issues with renames (fixes #1302) Extra comments explain current issues. --- internal/model/puller.go | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/internal/model/puller.go b/internal/model/puller.go index c0fbccbb7..dbf2a129a 100644 --- a/internal/model/puller.go +++ b/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