Fixed: Renaming episodes on OSX with case-insensitive filesystem.

This commit is contained in:
Taloth Saldono 2015-06-27 01:01:33 +02:00
parent bd222dbd95
commit c9f720885e
3 changed files with 89 additions and 8 deletions

View File

@ -129,6 +129,59 @@ namespace NzbDrone.Common.Test.DiskTests
VerifyDeletedFile(_sourcePath); VerifyDeletedFile(_sourcePath);
} }
[Test]
public void should_not_remove_source_if_partial_still_exists()
{
MonoOnly();
var targetPath = Path.Combine(Path.GetDirectoryName(_targetPath), Path.GetFileName(_targetPath).ToUpper());
var tempTargetPath = targetPath + ".partial~";
WithSuccessfulHardlink(_sourcePath, _backupPath);
WithExistingFile(_targetPath);
Mocker.GetMock<IDiskProvider>()
.Setup(v => v.MoveFile(_backupPath, tempTargetPath, false))
.Callback(() => WithExistingFile(tempTargetPath, true));
Mocker.GetMock<IDiskProvider>()
.Setup(v => v.MoveFile(tempTargetPath, targetPath, false))
.Callback(() => { });
Assert.Throws<IOException>(() => Subject.TransferFile(_sourcePath, targetPath, TransferMode.Move));
Mocker.GetMock<IDiskProvider>()
.Verify(v => v.DeleteFile(_sourcePath), Times.Never());
}
[Test]
public void should_rename_via_temp()
{
var targetPath = Path.Combine(Path.GetDirectoryName(_sourcePath), Path.GetFileName(_sourcePath).ToUpper());
Mocker.GetMock<IDiskProvider>()
.Setup(v => v.MoveFile(_sourcePath, _backupPath, false))
.Callback(() =>
{
WithExistingFile(_backupPath, true);
WithExistingFile(_sourcePath, false);
});
Mocker.GetMock<IDiskProvider>()
.Setup(v => v.MoveFile(_backupPath, targetPath, false))
.Callback(() =>
{
WithExistingFile(targetPath, true);
WithExistingFile(_backupPath, false);
});
var result = Subject.TransferFile(_sourcePath, targetPath, TransferMode.Move);
Mocker.GetMock<IDiskProvider>()
.Verify(v => v.MoveFile(_backupPath, targetPath, false), Times.Once());
}
[Test] [Test]
public void should_remove_backup_if_move_throws() public void should_remove_backup_if_move_throws()
{ {

View File

@ -83,11 +83,35 @@ namespace NzbDrone.Common.Disk
_logger.Debug("{0} [{1}] > [{2}]", mode, sourcePath, targetPath); _logger.Debug("{0} [{1}] > [{2}]", mode, sourcePath, targetPath);
if (sourcePath.PathEquals(targetPath)) if (sourcePath == targetPath)
{ {
throw new IOException(string.Format("Source and destination can't be the same {0}", sourcePath)); throw new IOException(string.Format("Source and destination can't be the same {0}", sourcePath));
} }
if (sourcePath.PathEquals(targetPath, StringComparison.InvariantCultureIgnoreCase))
{
if (mode.HasFlag(TransferMode.HardLink) || mode.HasFlag(TransferMode.Copy))
{
throw new IOException(string.Format("Source and destination can't be the same {0}", sourcePath));
}
if (mode.HasFlag(TransferMode.Move))
{
var tempPath = sourcePath + ".backup~";
_diskProvider.MoveFile(sourcePath, tempPath);
if (_diskProvider.FileExists(targetPath))
{
_diskProvider.MoveFile(tempPath, sourcePath);
}
_diskProvider.MoveFile(tempPath, targetPath);
return TransferMode.Move;
}
return TransferMode.None;
}
if (sourcePath.IsParentPath(targetPath)) if (sourcePath.IsParentPath(targetPath))
{ {
throw new IOException(string.Format("Destination cannot be a child of the source [{0}] => [{1}]", sourcePath, targetPath)); throw new IOException(string.Format("Destination cannot be a child of the source [{0}] => [{1}]", sourcePath, targetPath));
@ -220,6 +244,10 @@ namespace NzbDrone.Common.Disk
if (targetSize == originalSize) if (targetSize == originalSize)
{ {
_diskProvider.MoveFile(tempTargetPath, targetPath); _diskProvider.MoveFile(tempTargetPath, targetPath);
if (_diskProvider.FileExists(tempTargetPath))
{
throw new IOException(String.Format("Temporary file '{0}' still exists, aborting.", tempTargetPath));
}
_logger.Trace("Hardlink move succeeded, deleting source."); _logger.Trace("Hardlink move succeeded, deleting source.");
_diskProvider.DeleteFile(sourcePath); _diskProvider.DeleteFile(sourcePath);
return true; return true;

View File

@ -97,11 +97,11 @@ namespace NzbDrone.Core.MediaFiles
return TransferFile(episodeFile, localEpisode.Series, localEpisode.Episodes, filePath, TransferMode.Copy); return TransferFile(episodeFile, localEpisode.Series, localEpisode.Episodes, filePath, TransferMode.Copy);
} }
private EpisodeFile TransferFile(EpisodeFile episodeFile, Series series, List<Episode> episodes, string destinationFilename, TransferMode mode) private EpisodeFile TransferFile(EpisodeFile episodeFile, Series series, List<Episode> episodes, string destinationFilePath, TransferMode mode)
{ {
Ensure.That(episodeFile, () => episodeFile).IsNotNull(); Ensure.That(episodeFile, () => episodeFile).IsNotNull();
Ensure.That(series,() => series).IsNotNull(); Ensure.That(series,() => series).IsNotNull();
Ensure.That(destinationFilename, () => destinationFilename).IsValidPath(); Ensure.That(destinationFilePath, () => destinationFilePath).IsValidPath();
var episodeFilePath = episodeFile.Path ?? Path.Combine(series.Path, episodeFile.RelativePath); var episodeFilePath = episodeFile.Path ?? Path.Combine(series.Path, episodeFile.RelativePath);
@ -110,14 +110,14 @@ namespace NzbDrone.Core.MediaFiles
throw new FileNotFoundException("Episode file path does not exist", episodeFilePath); throw new FileNotFoundException("Episode file path does not exist", episodeFilePath);
} }
if (episodeFilePath.PathEquals(destinationFilename)) if (episodeFilePath == destinationFilePath)
{ {
throw new SameFilenameException("File not moved, source and destination are the same", episodeFilePath); throw new SameFilenameException("File not moved, source and destination are the same", episodeFilePath);
} }
_diskTransferService.TransferFile(episodeFilePath, destinationFilename, mode); _diskTransferService.TransferFile(episodeFilePath, destinationFilePath, mode);
episodeFile.RelativePath = series.Path.GetRelativePath(destinationFilename); episodeFile.RelativePath = series.Path.GetRelativePath(destinationFilePath);
_updateEpisodeFileService.ChangeFileDateForFile(episodeFile, series, episodes); _updateEpisodeFileService.ChangeFileDateForFile(episodeFile, series, episodes);
@ -127,7 +127,7 @@ namespace NzbDrone.Core.MediaFiles
if (series.SeasonFolder) if (series.SeasonFolder)
{ {
var seasonFolder = Path.GetDirectoryName(destinationFilename); var seasonFolder = Path.GetDirectoryName(destinationFilePath);
_mediaFileAttributeService.SetFolderLastWriteTime(seasonFolder, episodeFile.DateAdded); _mediaFileAttributeService.SetFolderLastWriteTime(seasonFolder, episodeFile.DateAdded);
} }
@ -138,7 +138,7 @@ namespace NzbDrone.Core.MediaFiles
_logger.WarnException("Unable to set last write time", ex); _logger.WarnException("Unable to set last write time", ex);
} }
_mediaFileAttributeService.SetFilePermissions(destinationFilename); _mediaFileAttributeService.SetFilePermissions(destinationFilePath);
return episodeFile; return episodeFile;
} }