Skip to content

Commit

Permalink
Fixed: Don't rollback file move if destination already exists
Browse files Browse the repository at this point in the history
(cherry picked from commit f05405fe1ce4c78a8c75e27920c863c5b83686bd)
(cherry picked from commit 8ab040f612ee04dac4813a08cdeaddd446a64dc9)
  • Loading branch information
markus101 authored and mynameisbogdan committed May 23, 2023
1 parent d0fbb1f commit c02bfb5
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 2 deletions.
20 changes: 20 additions & 0 deletions src/NzbDrone.Common.Test/DiskTests/DiskTransferServiceFixture.cs
Expand Up @@ -351,6 +351,26 @@ public void should_rollback_move_on_partial_if_source_remains()
.Verify(v => v.DeleteFile(_targetPath), Times.Once());
}

[Test]
public void should_not_rollback_move_on_partial_if_destination_already_exists()
{
Mocker.GetMock<IDiskProvider>()
.Setup(v => v.MoveFile(_sourcePath, _targetPath, false))
.Callback(() =>
{
WithExistingFile(_targetPath, true, 900);
});

Mocker.GetMock<IDiskProvider>()
.Setup(v => v.MoveFile(_sourcePath, _targetPath, false))
.Throws(new FileAlreadyExistsException("File already exists", _targetPath));

Assert.Throws<FileAlreadyExistsException>(() => Subject.TransferFile(_sourcePath, _targetPath, TransferMode.Move));

Mocker.GetMock<IDiskProvider>()
.Verify(v => v.DeleteFile(_targetPath), Times.Never());
}

[Test]
public void should_log_error_if_rollback_partialmove_fails()
{
Expand Down
5 changes: 5 additions & 0 deletions src/NzbDrone.Common/Disk/DiskProviderBase.cs
Expand Up @@ -264,6 +264,11 @@ public void MoveFolder(string source, string destination, bool overwrite = false

protected virtual void MoveFileInternal(string source, string destination)
{
if (File.Exists(destination))
{
throw new FileAlreadyExistsException("File already exists", destination);
}

File.Move(source, destination);
}

Expand Down
8 changes: 6 additions & 2 deletions src/NzbDrone.Common/Disk/DiskTransferService.cs
Expand Up @@ -500,9 +500,13 @@ private void TryMoveFileVerified(string sourcePath, string targetPath, long orig
throw new IOException(string.Format("File move incomplete, data loss may have occurred. [{0}] was {1} bytes long instead of the expected {2}.", targetPath, targetSize, originalSize));
}
}
catch
catch (Exception ex)
{
RollbackPartialMove(sourcePath, targetPath);
if (ex is not FileAlreadyExistsException)
{
RollbackPartialMove(sourcePath, targetPath);
}

throw;
}
}
Expand Down
15 changes: 15 additions & 0 deletions src/NzbDrone.Common/Disk/FileAlreadyExistsException.cs
@@ -0,0 +1,15 @@
using System;

namespace NzbDrone.Common.Disk
{
public class FileAlreadyExistsException : Exception
{
public string Filename { get; set; }

public FileAlreadyExistsException(string message, string filename)
: base(message)
{
Filename = filename;
}
}
}

0 comments on commit c02bfb5

Please sign in to comment.