lib/model: Don't fail over case-conflict on tempfile (fixes #6973) (#6975)

This commit is contained in:
Simon Frei 2020-09-09 11:47:14 +02:00 committed by GitHub
parent 44658258d2
commit e3cd9219b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 36 additions and 2 deletions

View File

@ -25,11 +25,11 @@ const (
)
type ErrCaseConflict struct {
given, real string
Given, Real string
}
func (e *ErrCaseConflict) Error() string {
return fmt.Sprintf(`given name "%v" differs from name in filesystem "%v"`, e.given, e.real)
return fmt.Sprintf(`given name "%v" differs from name in filesystem "%v"`, e.Given, e.Real)
}
func IsErrCaseConflict(err error) bool {

View File

@ -1060,6 +1060,14 @@ func (f *sendReceiveFolder) handleFile(file protocol.FileInfo, snap *db.Snapshot
// Check for an old temporary file which might have some blocks we could
// reuse.
tempBlocks, err := scanner.HashFile(f.ctx, f.fs, tempName, file.BlockSize(), nil, false)
if err != nil {
var caseErr *fs.ErrCaseConflict
if errors.As(err, &caseErr) {
if rerr := f.fs.Rename(caseErr.Real, tempName); rerr == nil {
tempBlocks, err = scanner.HashFile(f.ctx, f.fs, tempName, file.BlockSize(), nil, false)
}
}
}
if err == nil {
// Check for any reusable blocks in the temp file
tempCopyBlocks, _ := blockDiff(tempBlocks, file.Blocks)

View File

@ -1216,6 +1216,32 @@ func testPullCaseOnlyDirOrSymlink(t *testing.T, dir bool) {
}
}
func TestPullTempFileCaseConflict(t *testing.T) {
m, f := setupSendReceiveFolder()
defer cleanupSRFolder(f, m)
copyChan := make(chan copyBlocksState, 1)
file := protocol.FileInfo{Name: "foo"}
confl := "Foo"
tempNameConfl := fs.TempName(confl)
if fd, err := f.fs.Create(tempNameConfl); err != nil {
t.Fatal(err)
} else {
if _, err := fd.Write([]byte("data")); err != nil {
t.Fatal(err)
}
fd.Close()
}
f.handleFile(file, f.fset.Snapshot(), copyChan)
cs := <-copyChan
if _, err := cs.tempFile(); err != nil {
t.Error(err)
}
}
func cleanupSharedPullerState(s *sharedPullerState) {
s.mut.Lock()
defer s.mut.Unlock()