Fixed: Renaming episodes on OSX with case-insensitive filesystem.
This commit is contained in:
parent
bd222dbd95
commit
c9f720885e
|
@ -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()
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue