diff --git a/Emby.Drawing/Common/ImageHeader.cs b/Emby.Drawing/Common/ImageHeader.cs index b66bd71ea5..1c70b3bb6c 100644 --- a/Emby.Drawing/Common/ImageHeader.cs +++ b/Emby.Drawing/Common/ImageHeader.cs @@ -46,7 +46,7 @@ namespace Emby.Drawing.Common /// The image was of an unrecognised format. public static ImageSize GetDimensions(string path, ILogger logger, IFileSystem fileSystem) { - using (var fs = File.OpenRead(path)) + using (var fs = fileSystem.OpenRead(path)) { using (var binaryReader = new BinaryReader(fs)) { diff --git a/Emby.Drawing/GDI/GDIImageEncoder.cs b/Emby.Drawing/GDI/GDIImageEncoder.cs index 7e3ca530b5..1eabce74e0 100644 --- a/Emby.Drawing/GDI/GDIImageEncoder.cs +++ b/Emby.Drawing/GDI/GDIImageEncoder.cs @@ -66,7 +66,7 @@ namespace Emby.Drawing.GDI { using (var croppedImage = image.CropWhitespace()) { - Directory.CreateDirectory(Path.GetDirectoryName(outputPath)); + _fileSystem.CreateDirectory(Path.GetDirectoryName(outputPath)); using (var outputStream = _fileSystem.GetFileStream(outputPath, FileMode.Create, FileAccess.Write, FileShare.Read, false)) { @@ -120,7 +120,7 @@ namespace Emby.Drawing.GDI var outputFormat = GetOutputFormat(originalImage, selectedOutputFormat); - Directory.CreateDirectory(Path.GetDirectoryName(cacheFilePath)); + _fileSystem.CreateDirectory(Path.GetDirectoryName(cacheFilePath)); // Save to the cache location using (var cacheFileStream = _fileSystem.GetFileStream(cacheFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, false)) diff --git a/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs b/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs index 6ff40d1cf2..1fa93d5fbf 100644 --- a/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs +++ b/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs @@ -8,6 +8,7 @@ using MediaBrowser.Model.Logging; using System; using System.IO; using System.Linq; +using MediaBrowser.Common.IO; namespace Emby.Drawing.ImageMagick { @@ -15,13 +16,15 @@ namespace Emby.Drawing.ImageMagick { private readonly ILogger _logger; private readonly IApplicationPaths _appPaths; - private readonly IHttpClient _httpClient; + private readonly IHttpClient _httpClient; + private readonly IFileSystem _fileSystem; - public ImageMagickEncoder(ILogger logger, IApplicationPaths appPaths, IHttpClient httpClient) + public ImageMagickEncoder(ILogger logger, IApplicationPaths appPaths, IHttpClient httpClient, IFileSystem fileSystem) { _logger = logger; _appPaths = appPaths; _httpClient = httpClient; + _fileSystem = fileSystem; LogImageMagickVersion(); } @@ -77,7 +80,7 @@ namespace Emby.Drawing.ImageMagick try { var tmpPath = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid() + ".webp"); - Directory.CreateDirectory(Path.GetDirectoryName(tmpPath)); + _fileSystem.CreateDirectory(Path.GetDirectoryName(tmpPath)); using (var wand = new MagickWand(1, 1, new PixelWand("none", 1))) { @@ -181,7 +184,7 @@ namespace Emby.Drawing.ImageMagick { var currentImageSize = new ImageSize(imageWidth, imageHeight); - var task = new PlayedIndicatorDrawer(_appPaths, _httpClient).DrawPlayedIndicator(wand, currentImageSize); + var task = new PlayedIndicatorDrawer(_appPaths, _httpClient, _fileSystem).DrawPlayedIndicator(wand, currentImageSize); Task.WaitAll(task); } else if (options.UnplayedCount.HasValue) diff --git a/Emby.Drawing/ImageMagick/PlayedIndicatorDrawer.cs b/Emby.Drawing/ImageMagick/PlayedIndicatorDrawer.cs index 1c751de1fd..b5912788fa 100644 --- a/Emby.Drawing/ImageMagick/PlayedIndicatorDrawer.cs +++ b/Emby.Drawing/ImageMagick/PlayedIndicatorDrawer.cs @@ -5,6 +5,7 @@ using MediaBrowser.Model.Drawing; using System; using System.IO; using System.Threading.Tasks; +using MediaBrowser.Common.IO; namespace Emby.Drawing.ImageMagick { @@ -14,12 +15,14 @@ namespace Emby.Drawing.ImageMagick private const int OffsetFromTopRightCorner = 38; private readonly IApplicationPaths _appPaths; - private readonly IHttpClient _iHttpClient; + private readonly IHttpClient _iHttpClient; + private readonly IFileSystem _fileSystem; - public PlayedIndicatorDrawer(IApplicationPaths appPaths, IHttpClient iHttpClient) + public PlayedIndicatorDrawer(IApplicationPaths appPaths, IHttpClient iHttpClient, IFileSystem fileSystem) { _appPaths = appPaths; _iHttpClient = iHttpClient; + _fileSystem = fileSystem; } public async Task DrawPlayedIndicator(MagickWand wand, ImageSize imageSize) @@ -38,7 +41,7 @@ namespace Emby.Drawing.ImageMagick pixel.Opacity = 0; pixel.Color = "white"; draw.FillColor = pixel; - draw.Font = await DownloadFont("webdings.ttf", "https://github.com/MediaBrowser/Emby.Resources/raw/master/fonts/webdings.ttf", _appPaths, _iHttpClient).ConfigureAwait(false); + draw.Font = await DownloadFont("webdings.ttf", "https://github.com/MediaBrowser/Emby.Resources/raw/master/fonts/webdings.ttf", _appPaths, _iHttpClient, _fileSystem).ConfigureAwait(false); draw.FontSize = FontSize; draw.FontStyle = FontStyleType.NormalStyle; draw.TextAlignment = TextAlignType.CenterAlign; @@ -52,18 +55,18 @@ namespace Emby.Drawing.ImageMagick } } - internal static string ExtractFont(string name, IApplicationPaths paths) + internal static string ExtractFont(string name, IApplicationPaths paths, IFileSystem fileSystem) { var filePath = Path.Combine(paths.ProgramDataPath, "fonts", name); - if (File.Exists(filePath)) + if (fileSystem.FileExists(filePath)) { return filePath; } var namespacePath = typeof(PlayedIndicatorDrawer).Namespace + ".fonts." + name; var tempPath = Path.Combine(paths.TempDirectory, Guid.NewGuid().ToString("N") + ".ttf"); - Directory.CreateDirectory(Path.GetDirectoryName(tempPath)); + fileSystem.CreateDirectory(Path.GetDirectoryName(tempPath)); using (var stream = typeof(PlayedIndicatorDrawer).Assembly.GetManifestResourceStream(namespacePath)) { @@ -73,11 +76,11 @@ namespace Emby.Drawing.ImageMagick } } - Directory.CreateDirectory(Path.GetDirectoryName(filePath)); + fileSystem.CreateDirectory(Path.GetDirectoryName(filePath)); try { - File.Copy(tempPath, filePath, false); + fileSystem.CopyFile(tempPath, filePath, false); } catch (IOException) { @@ -87,11 +90,11 @@ namespace Emby.Drawing.ImageMagick return tempPath; } - internal static async Task DownloadFont(string name, string url, IApplicationPaths paths, IHttpClient httpClient) + internal static async Task DownloadFont(string name, string url, IApplicationPaths paths, IHttpClient httpClient, IFileSystem fileSystem) { var filePath = Path.Combine(paths.ProgramDataPath, "fonts", name); - if (File.Exists(filePath)) + if (fileSystem.FileExists(filePath)) { return filePath; } @@ -103,11 +106,11 @@ namespace Emby.Drawing.ImageMagick }).ConfigureAwait(false); - Directory.CreateDirectory(Path.GetDirectoryName(filePath)); + fileSystem.CreateDirectory(Path.GetDirectoryName(filePath)); try { - File.Copy(tempPath, filePath, false); + fileSystem.CopyFile(tempPath, filePath, false); } catch (IOException) { diff --git a/Emby.Drawing/ImageMagick/StripCollageBuilder.cs b/Emby.Drawing/ImageMagick/StripCollageBuilder.cs index 7ed0f36e2c..92eb1cd597 100644 --- a/Emby.Drawing/ImageMagick/StripCollageBuilder.cs +++ b/Emby.Drawing/ImageMagick/StripCollageBuilder.cs @@ -2,16 +2,19 @@ using MediaBrowser.Common.Configuration; using System; using System.Collections.Generic; +using MediaBrowser.Common.IO; namespace Emby.Drawing.ImageMagick { public class StripCollageBuilder { private readonly IApplicationPaths _appPaths; + private readonly IFileSystem _fileSystem; - public StripCollageBuilder(IApplicationPaths appPaths) + public StripCollageBuilder(IApplicationPaths appPaths, IFileSystem fileSystem) { _appPaths = appPaths; + _fileSystem = fileSystem; } public void BuildPosterCollage(List paths, string outputPath, int width, int height, string text) @@ -490,7 +493,7 @@ namespace Emby.Drawing.ImageMagick private string MontserratLightFont { - get { return PlayedIndicatorDrawer.ExtractFont("MontserratLight.otf", _appPaths); } + get { return PlayedIndicatorDrawer.ExtractFont("MontserratLight.otf", _appPaths, _fileSystem); } } } } diff --git a/Emby.Drawing/ImageMagick/UnplayedCountIndicator.cs b/Emby.Drawing/ImageMagick/UnplayedCountIndicator.cs index dd25004d66..d63abd2a5a 100644 --- a/Emby.Drawing/ImageMagick/UnplayedCountIndicator.cs +++ b/Emby.Drawing/ImageMagick/UnplayedCountIndicator.cs @@ -33,7 +33,7 @@ namespace Emby.Drawing.ImageMagick pixel.Opacity = 0; pixel.Color = "white"; draw.FillColor = pixel; - draw.Font = PlayedIndicatorDrawer.ExtractFont("robotoregular.ttf", _appPaths); + draw.Font = PlayedIndicatorDrawer.ExtractFont("robotoregular.ttf", _appPaths, _fileSystem); draw.FontStyle = FontStyleType.NormalStyle; draw.TextAlignment = TextAlignType.CenterAlign; draw.FontWeight = FontWeightType.RegularStyle; diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs index 231bfa2b47..d4fce76d02 100644 --- a/Emby.Drawing/ImageProcessor.cs +++ b/Emby.Drawing/ImageProcessor.cs @@ -215,12 +215,12 @@ namespace Emby.Drawing { CheckDisposed(); - if (!File.Exists(cacheFilePath)) + if (!_fileSystem.FileExists(cacheFilePath)) { var newWidth = Convert.ToInt32(newSize.Width); var newHeight = Convert.ToInt32(newSize.Height); - Directory.CreateDirectory(Path.GetDirectoryName(cacheFilePath)); + _fileSystem.CreateDirectory(Path.GetDirectoryName(cacheFilePath)); await _imageProcessingSemaphore.WaitAsync().ConfigureAwait(false); @@ -270,7 +270,7 @@ namespace Emby.Drawing await semaphore.WaitAsync().ConfigureAwait(false); // Check again in case of contention - if (File.Exists(croppedImagePath)) + if (_fileSystem.FileExists(croppedImagePath)) { semaphore.Release(); return GetResult(croppedImagePath); @@ -280,7 +280,7 @@ namespace Emby.Drawing try { - Directory.CreateDirectory(Path.GetDirectoryName(croppedImagePath)); + _fileSystem.CreateDirectory(Path.GetDirectoryName(croppedImagePath)); await _imageProcessingSemaphore.WaitAsync().ConfigureAwait(false); imageProcessingLockTaken = true; @@ -366,7 +366,7 @@ namespace Emby.Drawing /// ImageSize. public ImageSize GetImageSize(string path) { - return GetImageSize(path, File.GetLastWriteTimeUtc(path), false); + return GetImageSize(path, _fileSystem.GetLastWriteTimeUtc(path), false); } public ImageSize GetImageSize(ItemImageInfo info) @@ -452,7 +452,7 @@ namespace Emby.Drawing try { var path = ImageSizeFile; - Directory.CreateDirectory(Path.GetDirectoryName(path)); + _fileSystem.CreateDirectory(Path.GetDirectoryName(path)); _jsonSerializer.SerializeToFile(_cachedImagedSizes, path); } catch (Exception ex) @@ -624,7 +624,7 @@ namespace Emby.Drawing await semaphore.WaitAsync().ConfigureAwait(false); // Check again in case of contention - if (File.Exists(enhancedImagePath)) + if (_fileSystem.FileExists(enhancedImagePath)) { semaphore.Release(); return enhancedImagePath; @@ -634,7 +634,7 @@ namespace Emby.Drawing try { - Directory.CreateDirectory(Path.GetDirectoryName(enhancedImagePath)); + _fileSystem.CreateDirectory(Path.GetDirectoryName(enhancedImagePath)); await _imageProcessingSemaphore.WaitAsync().ConfigureAwait(false); diff --git a/MediaBrowser.Api/AppThemeService.cs b/MediaBrowser.Api/AppThemeService.cs deleted file mode 100644 index 87084e415a..0000000000 --- a/MediaBrowser.Api/AppThemeService.cs +++ /dev/null @@ -1,100 +0,0 @@ -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.Net; -using MediaBrowser.Controller.Themes; -using MediaBrowser.Model.Themes; -using ServiceStack; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; - -namespace MediaBrowser.Api -{ - [Route("/Themes", "GET", Summary = "Gets a list of available themes for an app")] - public class GetAppThemes : IReturn> - { - [ApiMember(Name = "App", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] - public string App { get; set; } - } - - [Route("/Themes/Info", "GET", Summary = "Gets an app theme")] - public class GetAppTheme : IReturn - { - [ApiMember(Name = "App", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] - public string App { get; set; } - - [ApiMember(Name = "Name", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] - public string Name { get; set; } - } - - [Route("/Themes/Images", "GET", Summary = "Gets an app theme")] - public class GetAppThemeImage - { - [ApiMember(Name = "App", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] - public string App { get; set; } - - [ApiMember(Name = "Theme", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] - public string Theme { get; set; } - - [ApiMember(Name = "Name", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] - public string Name { get; set; } - - [ApiMember(Name = "CacheTag", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] - public string CacheTag { get; set; } - } - - [Route("/Themes", "POST", Summary = "Saves a theme")] - public class SaveTheme : AppTheme, IReturnVoid - { - } - - [Authenticated] - public class AppThemeService : BaseApiService - { - private readonly IAppThemeManager _themeManager; - private readonly IFileSystem _fileSystem; - - public AppThemeService(IAppThemeManager themeManager, IFileSystem fileSystem) - { - _themeManager = themeManager; - _fileSystem = fileSystem; - } - - public object Get(GetAppThemes request) - { - var result = _themeManager.GetThemes(request.App).ToList(); - - return ToOptimizedResult(result); - } - - public object Get(GetAppTheme request) - { - var result = _themeManager.GetTheme(request.App, request.Name); - - return ToOptimizedResult(result); - } - - public void Post(SaveTheme request) - { - _themeManager.SaveTheme(request); - } - - public object Get(GetAppThemeImage request) - { - var info = _themeManager.GetImageImageInfo(request.App, request.Theme, request.Name); - - var cacheGuid = new Guid(info.CacheTag); - - TimeSpan? cacheDuration = null; - - if (!string.IsNullOrEmpty(request.CacheTag) && cacheGuid == new Guid(request.CacheTag)) - { - cacheDuration = TimeSpan.FromDays(365); - } - - var contentType = MimeTypes.GetMimeType(info.Path); - - return ResultFactory.GetCachedResult(Request, cacheGuid, null, cacheDuration, () => _fileSystem.GetFileStream(info.Path, FileMode.Open, FileAccess.Read, FileShare.Read), contentType); - } - } -} diff --git a/MediaBrowser.Api/EnvironmentService.cs b/MediaBrowser.Api/EnvironmentService.cs index 457b4709bf..8160c6a167 100644 --- a/MediaBrowser.Api/EnvironmentService.cs +++ b/MediaBrowser.Api/EnvironmentService.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; +using MediaBrowser.Common.IO; namespace MediaBrowser.Api { @@ -96,13 +97,14 @@ namespace MediaBrowser.Api /// The _network manager /// private readonly INetworkManager _networkManager; + private IFileSystem _fileSystem; /// /// Initializes a new instance of the class. /// /// The network manager. /// networkManager - public EnvironmentService(INetworkManager networkManager) + public EnvironmentService(INetworkManager networkManager, IFileSystem fileSystem) { if (networkManager == null) { @@ -110,6 +112,7 @@ namespace MediaBrowser.Api } _networkManager = networkManager; + _fileSystem = fileSystem; } /// @@ -222,8 +225,7 @@ namespace MediaBrowser.Api private IEnumerable GetFileSystemEntries(GetDirectoryContents request) { // using EnumerateFileSystemInfos doesn't handle reparse points (symlinks) - var entries = new DirectoryInfo(request.Path).EnumerateDirectories("*", SearchOption.TopDirectoryOnly) - .Concat(new DirectoryInfo(request.Path).EnumerateFiles("*", SearchOption.TopDirectoryOnly)).Where(i => + var entries = _fileSystem.GetFileSystemEntries(request.Path).Where(i => { if (!request.IncludeHidden && i.Attributes.HasFlag(FileAttributes.Hidden)) { diff --git a/MediaBrowser.Api/Images/ImageByNameService.cs b/MediaBrowser.Api/Images/ImageByNameService.cs index b4d5a99497..a6e1af516c 100644 --- a/MediaBrowser.Api/Images/ImageByNameService.cs +++ b/MediaBrowser.Api/Images/ImageByNameService.cs @@ -130,8 +130,7 @@ namespace MediaBrowser.Api.Images { try { - return new DirectoryInfo(path) - .GetFiles("*", SearchOption.AllDirectories) + return _fileSystem.GetFiles(path) .Where(i => BaseItem.SupportedImageExtensions.Contains(i.Extension, StringComparer.Ordinal)) .Select(i => new ImageByNameInfo { @@ -184,7 +183,7 @@ namespace MediaBrowser.Api.Images var paths = BaseItem.SupportedImageExtensions.Select(i => Path.Combine(_appPaths.GeneralPath, request.Name, filename + i)).ToList(); - var path = paths.FirstOrDefault(File.Exists) ?? paths.FirstOrDefault(); + var path = paths.FirstOrDefault(_fileSystem.FileExists) ?? paths.FirstOrDefault(); return ToStaticFileResult(path); } @@ -198,11 +197,11 @@ namespace MediaBrowser.Api.Images { var themeFolder = Path.Combine(_appPaths.RatingsPath, request.Theme); - if (Directory.Exists(themeFolder)) + if (_fileSystem.DirectoryExists(themeFolder)) { var path = BaseItem.SupportedImageExtensions .Select(i => Path.Combine(themeFolder, request.Name + i)) - .FirstOrDefault(File.Exists); + .FirstOrDefault(_fileSystem.FileExists); if (!string.IsNullOrEmpty(path)) { @@ -212,14 +211,14 @@ namespace MediaBrowser.Api.Images var allFolder = Path.Combine(_appPaths.RatingsPath, "all"); - if (Directory.Exists(allFolder)) + if (_fileSystem.DirectoryExists(allFolder)) { // Avoid implicitly captured closure var currentRequest = request; var path = BaseItem.SupportedImageExtensions .Select(i => Path.Combine(allFolder, currentRequest.Name + i)) - .FirstOrDefault(File.Exists); + .FirstOrDefault(_fileSystem.FileExists); if (!string.IsNullOrEmpty(path)) { @@ -239,10 +238,10 @@ namespace MediaBrowser.Api.Images { var themeFolder = Path.Combine(_appPaths.MediaInfoImagesPath, request.Theme); - if (Directory.Exists(themeFolder)) + if (_fileSystem.DirectoryExists(themeFolder)) { var path = BaseItem.SupportedImageExtensions.Select(i => Path.Combine(themeFolder, request.Name + i)) - .FirstOrDefault(File.Exists); + .FirstOrDefault(_fileSystem.FileExists); if (!string.IsNullOrEmpty(path)) { @@ -252,13 +251,13 @@ namespace MediaBrowser.Api.Images var allFolder = Path.Combine(_appPaths.MediaInfoImagesPath, "all"); - if (Directory.Exists(allFolder)) + if (_fileSystem.DirectoryExists(allFolder)) { // Avoid implicitly captured closure var currentRequest = request; var path = BaseItem.SupportedImageExtensions.Select(i => Path.Combine(allFolder, currentRequest.Name + i)) - .FirstOrDefault(File.Exists); + .FirstOrDefault(_fileSystem.FileExists); if (!string.IsNullOrEmpty(path)) { diff --git a/MediaBrowser.Api/Images/RemoteImageService.cs b/MediaBrowser.Api/Images/RemoteImageService.cs index 6d2579ea9f..c67ef96c96 100644 --- a/MediaBrowser.Api/Images/RemoteImageService.cs +++ b/MediaBrowser.Api/Images/RemoteImageService.cs @@ -237,7 +237,7 @@ namespace MediaBrowser.Api.Images contentPath = await reader.ReadToEndAsync().ConfigureAwait(false); } - if (File.Exists(contentPath)) + if (_fileSystem.FileExists(contentPath)) { return ToStaticFileResult(contentPath); } @@ -281,7 +281,7 @@ namespace MediaBrowser.Api.Images var fullCachePath = GetFullCachePath(urlHash + "." + ext); - Directory.CreateDirectory(Path.GetDirectoryName(fullCachePath)); + _fileSystem.CreateDirectory(Path.GetDirectoryName(fullCachePath)); using (var stream = result.Content) { using (var filestream = _fileSystem.GetFileStream(fullCachePath, FileMode.Create, FileAccess.Write, FileShare.Read, true)) @@ -290,7 +290,7 @@ namespace MediaBrowser.Api.Images } } - Directory.CreateDirectory(Path.GetDirectoryName(pointerCachePath)); + _fileSystem.CreateDirectory(Path.GetDirectoryName(pointerCachePath)); using (var writer = new StreamWriter(pointerCachePath)) { await writer.WriteAsync(fullCachePath).ConfigureAwait(false); diff --git a/MediaBrowser.Api/ItemLookupService.cs b/MediaBrowser.Api/ItemLookupService.cs index a0ba6e61f8..9f7f57155b 100644 --- a/MediaBrowser.Api/ItemLookupService.cs +++ b/MediaBrowser.Api/ItemLookupService.cs @@ -200,7 +200,7 @@ namespace MediaBrowser.Api //} item.ProviderIds = request.ProviderIds; - var task = _providerManager.RefreshFullItem(item, new MetadataRefreshOptions + var task = _providerManager.RefreshFullItem(item, new MetadataRefreshOptions(_fileSystem) { MetadataRefreshMode = MetadataRefreshMode.FullRefresh, ImageRefreshMode = ImageRefreshMode.FullRefresh, @@ -230,7 +230,7 @@ namespace MediaBrowser.Api contentPath = await reader.ReadToEndAsync().ConfigureAwait(false); } - if (File.Exists(contentPath)) + if (_fileSystem.FileExists(contentPath)) { return ToStaticFileResult(contentPath); } @@ -271,7 +271,7 @@ namespace MediaBrowser.Api var fullCachePath = GetFullCachePath(urlHash + "." + ext); - Directory.CreateDirectory(Path.GetDirectoryName(fullCachePath)); + _fileSystem.CreateDirectory(Path.GetDirectoryName(fullCachePath)); using (var stream = result.Content) { using (var filestream = _fileSystem.GetFileStream(fullCachePath, FileMode.Create, FileAccess.Write, FileShare.Read, true)) @@ -280,7 +280,7 @@ namespace MediaBrowser.Api } } - Directory.CreateDirectory(Path.GetDirectoryName(pointerCachePath)); + _fileSystem.CreateDirectory(Path.GetDirectoryName(pointerCachePath)); using (var writer = new StreamWriter(pointerCachePath)) { await writer.WriteAsync(fullCachePath).ConfigureAwait(false); diff --git a/MediaBrowser.Api/ItemRefreshService.cs b/MediaBrowser.Api/ItemRefreshService.cs index f56fd32828..7eb0b87dda 100644 --- a/MediaBrowser.Api/ItemRefreshService.cs +++ b/MediaBrowser.Api/ItemRefreshService.cs @@ -66,7 +66,7 @@ namespace MediaBrowser.Api private MetadataRefreshOptions GetRefreshOptions(BaseRefreshRequest request) { - return new MetadataRefreshOptions(new DirectoryService()) + return new MetadataRefreshOptions(new DirectoryService(_fileSystem)) { MetadataRefreshMode = request.MetadataRefreshMode, ImageRefreshMode = request.ImageRefreshMode, diff --git a/MediaBrowser.Api/Library/LibraryHelpers.cs b/MediaBrowser.Api/Library/LibraryHelpers.cs index 0ee28d6fef..5e40ac635f 100644 --- a/MediaBrowser.Api/Library/LibraryHelpers.cs +++ b/MediaBrowser.Api/Library/LibraryHelpers.cs @@ -33,7 +33,7 @@ namespace MediaBrowser.Api.Library var rootFolderPath = appPaths.DefaultUserViewsPath; var path = Path.Combine(rootFolderPath, virtualFolderName); - if (!Directory.Exists(path)) + if (!fileSystem.DirectoryExists(path)) { throw new DirectoryNotFoundException(string.Format("The media collection {0} does not exist", virtualFolderName)); } @@ -57,7 +57,7 @@ namespace MediaBrowser.Api.Library /// The path is not valid. public static void AddMediaPath(IFileSystem fileSystem, string virtualFolderName, string path, IServerApplicationPaths appPaths) { - if (!Directory.Exists(path)) + if (!fileSystem.DirectoryExists(path)) { throw new DirectoryNotFoundException("The path does not exist."); } @@ -69,7 +69,7 @@ namespace MediaBrowser.Api.Library var lnk = Path.Combine(virtualFolderPath, shortcutFilename + ShortcutFileExtension); - while (File.Exists(lnk)) + while (fileSystem.FileExists(lnk)) { shortcutFilename += "1"; lnk = Path.Combine(virtualFolderPath, shortcutFilename + ShortcutFileExtension); diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs index 49dd121baa..9106d86ff5 100644 --- a/MediaBrowser.Api/Library/LibraryService.cs +++ b/MediaBrowser.Api/Library/LibraryService.cs @@ -557,7 +557,7 @@ namespace MediaBrowser.Api.Library { throw new ArgumentException("This command cannot be used for remote or virtual items."); } - if (Directory.Exists(item.Path)) + if (_fileSystem.DirectoryExists(item.Path)) { throw new ArgumentException("This command cannot be used for directories."); } diff --git a/MediaBrowser.Api/Library/LibraryStructureService.cs b/MediaBrowser.Api/Library/LibraryStructureService.cs index f5fe921cec..c9baf5c376 100644 --- a/MediaBrowser.Api/Library/LibraryStructureService.cs +++ b/MediaBrowser.Api/Library/LibraryStructureService.cs @@ -195,7 +195,7 @@ namespace MediaBrowser.Api.Library var virtualFolderPath = Path.Combine(rootFolderPath, name); - if (Directory.Exists(virtualFolderPath)) + if (_fileSystem.DirectoryExists(virtualFolderPath)) { throw new ArgumentException("There is already a media collection with the name " + name + "."); } @@ -204,13 +204,13 @@ namespace MediaBrowser.Api.Library try { - Directory.CreateDirectory(virtualFolderPath); + _fileSystem.CreateDirectory(virtualFolderPath); if (!string.IsNullOrEmpty(request.CollectionType)) { var path = Path.Combine(virtualFolderPath, request.CollectionType + ".collection"); - File.Create(path); + _fileSystem.CreateFile(path); } } finally @@ -256,12 +256,12 @@ namespace MediaBrowser.Api.Library var currentPath = Path.Combine(rootFolderPath, request.Name); var newPath = Path.Combine(rootFolderPath, request.NewName); - if (!Directory.Exists(currentPath)) + if (!_fileSystem.DirectoryExists(currentPath)) { throw new DirectoryNotFoundException("The media collection does not exist"); } - if (!string.Equals(currentPath, newPath, StringComparison.OrdinalIgnoreCase) && Directory.Exists(newPath)) + if (!string.Equals(currentPath, newPath, StringComparison.OrdinalIgnoreCase) && _fileSystem.DirectoryExists(newPath)) { throw new ArgumentException("There is already a media collection with the name " + newPath + "."); } @@ -276,11 +276,11 @@ namespace MediaBrowser.Api.Library //Create an unique name var temporaryName = Guid.NewGuid().ToString(); var temporaryPath = Path.Combine(rootFolderPath, temporaryName); - Directory.Move(currentPath, temporaryPath); + _fileSystem.MoveDirectory(currentPath, temporaryPath); currentPath = temporaryPath; } - Directory.Move(currentPath, newPath); + _fileSystem.MoveDirectory(currentPath, newPath); } finally { @@ -319,7 +319,7 @@ namespace MediaBrowser.Api.Library var path = Path.Combine(rootFolderPath, request.Name); - if (!Directory.Exists(path)) + if (!_fileSystem.DirectoryExists(path)) { throw new DirectoryNotFoundException("The media folder does not exist"); } diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj index 7fa631e218..901dd11e2a 100644 --- a/MediaBrowser.Api/MediaBrowser.Api.csproj +++ b/MediaBrowser.Api/MediaBrowser.Api.csproj @@ -11,10 +11,10 @@ MediaBrowser.Api 512 ..\ - 10.0.0 - 2.0 v4.5 true + + true @@ -25,7 +25,6 @@ prompt 4 AnyCPU - v4.5 none @@ -34,7 +33,6 @@ TRACE prompt 4 - v4.5 none @@ -43,16 +41,11 @@ TRACE prompt 4 - v4.5 Always - - False - ..\packages\morelinq.1.1.1\lib\net35\MoreLinq.dll - @@ -64,12 +57,14 @@ ..\ThirdParty\ServiceStack.Text\ServiceStack.Text.dll + + ..\packages\morelinq.1.1.1\lib\net35\MoreLinq.dll + Properties\SharedVersion.cs - diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 531d67eedd..a524490783 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -889,7 +889,7 @@ namespace MediaBrowser.Api.Playback CancellationTokenSource cancellationTokenSource, string workingDirectory = null) { - Directory.CreateDirectory(Path.GetDirectoryName(outputPath)); + FileSystem.CreateDirectory(Path.GetDirectoryName(outputPath)); await AcquireResources(state, cancellationTokenSource).ConfigureAwait(false); @@ -942,7 +942,7 @@ namespace MediaBrowser.Api.Playback Logger.Info(commandLineLogMessage); var logFilePath = Path.Combine(ServerConfigurationManager.ApplicationPaths.LogDirectoryPath, "transcode-" + Guid.NewGuid() + ".txt"); - Directory.CreateDirectory(Path.GetDirectoryName(logFilePath)); + FileSystem.CreateDirectory(Path.GetDirectoryName(logFilePath)); // FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory. state.LogFileStream = FileSystem.GetFileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, true); @@ -972,7 +972,7 @@ namespace MediaBrowser.Api.Playback StartStreamingLog(transcodingJob, state, process.StandardError.BaseStream, state.LogFileStream); // Wait for the file to exist before proceeeding - while (!File.Exists(state.WaitForPath ?? outputPath) && !transcodingJob.HasExited) + while (!FileSystem.FileExists(state.WaitForPath ?? outputPath) && !transcodingJob.HasExited) { await Task.Delay(100, cancellationTokenSource.Token).ConfigureAwait(false); } diff --git a/MediaBrowser.Api/Playback/Dash/MpegDashService.cs b/MediaBrowser.Api/Playback/Dash/MpegDashService.cs index c201ffd587..8864848011 100644 --- a/MediaBrowser.Api/Playback/Dash/MpegDashService.cs +++ b/MediaBrowser.Api/Playback/Dash/MpegDashService.cs @@ -174,7 +174,7 @@ namespace MediaBrowser.Api.Playback.Dash var workingDirectory = Path.Combine(Path.GetDirectoryName(playlistPath), (startNumber == -1 ? 0 : startNumber).ToString(CultureInfo.InvariantCulture)); state.WaitForPath = Path.Combine(workingDirectory, Path.GetFileName(playlistPath)); - Directory.CreateDirectory(workingDirectory); + FileSystem.CreateDirectory(workingDirectory); job = await StartFfMpeg(state, playlistPath, cancellationTokenSource, workingDirectory).ConfigureAwait(false); await WaitForMinimumDashSegmentCount(Path.Combine(workingDirectory, Path.GetFileName(playlistPath)), 1, cancellationTokenSource.Token).ConfigureAwait(false); } @@ -328,8 +328,7 @@ namespace MediaBrowser.Api.Playback.Dash try { - return new DirectoryInfo(folder) - .EnumerateFiles("*", SearchOption.AllDirectories) + return fileSystem.GetFiles(folder) .Where(i => string.Equals(i.Extension, segmentExtension, StringComparison.OrdinalIgnoreCase)) .OrderByDescending(fileSystem.GetLastWriteTimeUtc) .Take(count) @@ -348,12 +347,12 @@ namespace MediaBrowser.Api.Playback.Dash if (requestedIndex == -1) { var path = Path.Combine(folder, "0", "stream" + representationId + "-" + "init" + segmentExtension); - return File.Exists(path) ? path : null; + return FileSystem.FileExists(path) ? path : null; } try { - foreach (var subfolder in new DirectoryInfo(folder).EnumerateDirectories().ToList()) + foreach (var subfolder in FileSystem.GetDirectories(folder).ToList()) { var subfolderName = Path.GetFileNameWithoutExtension(subfolder.FullName); int startNumber; @@ -361,7 +360,7 @@ namespace MediaBrowser.Api.Playback.Dash { var segmentIndex = requestedIndex - startNumber + 1; var path = Path.Combine(folder, subfolderName, "stream" + representationId + "-" + segmentIndex.ToString("00000", CultureInfo.InvariantCulture) + segmentExtension); - if (File.Exists(path)) + if (FileSystem.FileExists(path)) { return path; } diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs index e4f00e2a08..036397b4f5 100644 --- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs @@ -90,12 +90,12 @@ namespace MediaBrowser.Api.Playback.Hls TranscodingJob job = null; var playlist = state.OutputFilePath; - if (!File.Exists(playlist)) + if (!FileSystem.FileExists(playlist)) { await ApiEntryPoint.Instance.TranscodingStartLock.WaitAsync(cancellationTokenSource.Token).ConfigureAwait(false); try { - if (!File.Exists(playlist)) + if (!FileSystem.FileExists(playlist)) { // If the playlist doesn't already exist, startup ffmpeg try diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index 7b2844cd4b..9359c65f26 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -165,7 +165,7 @@ namespace MediaBrowser.Api.Playback.Hls TranscodingJob job = null; - if (File.Exists(segmentPath)) + if (FileSystem.FileExists(segmentPath)) { job = ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlistPath, TranscodingJobType); return await GetSegmentResult(state, playlistPath, segmentPath, requestedIndex, job, cancellationToken).ConfigureAwait(false); @@ -174,7 +174,7 @@ namespace MediaBrowser.Api.Playback.Hls await ApiEntryPoint.Instance.TranscodingStartLock.WaitAsync(cancellationTokenSource.Token).ConfigureAwait(false); try { - if (File.Exists(segmentPath)) + if (FileSystem.FileExists(segmentPath)) { job = ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlistPath, TranscodingJobType); return await GetSegmentResult(state, playlistPath, segmentPath, requestedIndex, job, cancellationToken).ConfigureAwait(false); @@ -386,8 +386,7 @@ namespace MediaBrowser.Api.Playback.Hls try { - return new DirectoryInfo(folder) - .EnumerateFiles("*", SearchOption.TopDirectoryOnly) + return fileSystem.GetFiles(folder) .Where(i => string.Equals(i.Extension, segmentExtension, StringComparison.OrdinalIgnoreCase) && Path.GetFileNameWithoutExtension(i.Name).StartsWith(filePrefix, StringComparison.OrdinalIgnoreCase)) .OrderByDescending(fileSystem.GetLastWriteTimeUtc) .FirstOrDefault(); @@ -432,7 +431,7 @@ namespace MediaBrowser.Api.Playback.Hls CancellationToken cancellationToken) { // If all transcoding has completed, just return immediately - if (transcodingJob != null && transcodingJob.HasExited && File.Exists(segmentPath)) + if (transcodingJob != null && transcodingJob.HasExited && FileSystem.FileExists(segmentPath)) { return GetSegmentResult(state, segmentPath, segmentIndex, transcodingJob); } @@ -452,7 +451,7 @@ namespace MediaBrowser.Api.Playback.Hls // If it appears in the playlist, it's done if (text.IndexOf(segmentFilename, StringComparison.OrdinalIgnoreCase) != -1) { - if (File.Exists(segmentPath)) + if (FileSystem.FileExists(segmentPath)) { return GetSegmentResult(state, segmentPath, segmentIndex, transcodingJob); } diff --git a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs index 910ac18e7b..aa0cda133b 100644 --- a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs +++ b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs @@ -139,7 +139,7 @@ namespace MediaBrowser.Api.Playback.Progressive } var outputPath = state.OutputFilePath; - var outputPathExists = File.Exists(outputPath); + var outputPathExists = FileSystem.FileExists(outputPath); var isTranscodeCached = outputPathExists && !ApiEntryPoint.Instance.HasActiveTranscodingJob(outputPath, TranscodingJobType.Progressive); @@ -325,7 +325,7 @@ namespace MediaBrowser.Api.Playback.Progressive { TranscodingJob job; - if (!File.Exists(outputPath)) + if (!FileSystem.FileExists(outputPath)) { job = await StartFfMpeg(state, outputPath, cancellationTokenSource).ConfigureAwait(false); } diff --git a/MediaBrowser.Api/Subtitles/SubtitleService.cs b/MediaBrowser.Api/Subtitles/SubtitleService.cs index c9280b6f63..6cfd07caca 100644 --- a/MediaBrowser.Api/Subtitles/SubtitleService.cs +++ b/MediaBrowser.Api/Subtitles/SubtitleService.cs @@ -259,7 +259,7 @@ namespace MediaBrowser.Api.Subtitles await _subtitleManager.DownloadSubtitles(video, request.SubtitleId, CancellationToken.None) .ConfigureAwait(false); - _providerManager.QueueRefresh(video.Id, new MetadataRefreshOptions()); + _providerManager.QueueRefresh(video.Id, new MetadataRefreshOptions(_fileSystem)); } catch (Exception ex) { diff --git a/MediaBrowser.Api/System/SystemService.cs b/MediaBrowser.Api/System/SystemService.cs index aa12269019..00935dd1e1 100644 --- a/MediaBrowser.Api/System/SystemService.cs +++ b/MediaBrowser.Api/System/SystemService.cs @@ -122,8 +122,7 @@ namespace MediaBrowser.Api.System try { - files = new DirectoryInfo(_appPaths.LogDirectoryPath) - .EnumerateFiles("*", SearchOption.AllDirectories) + files = _fileSystem.GetFiles(_appPaths.LogDirectoryPath) .Where(i => string.Equals(i.Extension, ".txt", StringComparison.OrdinalIgnoreCase)) .ToList(); } @@ -149,8 +148,7 @@ namespace MediaBrowser.Api.System public object Get(GetLogFile request) { - var file = new DirectoryInfo(_appPaths.LogDirectoryPath) - .EnumerateFiles("*", SearchOption.AllDirectories) + var file = _fileSystem.GetFiles(_appPaths.LogDirectoryPath) .First(i => string.Equals(i.Name, request.Name, StringComparison.OrdinalIgnoreCase)); return ResultFactory.GetStaticFileResult(Request, file.FullName, FileShare.ReadWrite); diff --git a/MediaBrowser.Common.Implementations/Archiving/ZipClient.cs b/MediaBrowser.Common.Implementations/Archiving/ZipClient.cs index cdcbc311a1..1377e9d552 100644 --- a/MediaBrowser.Common.Implementations/Archiving/ZipClient.cs +++ b/MediaBrowser.Common.Implementations/Archiving/ZipClient.cs @@ -7,6 +7,7 @@ using SharpCompress.Reader; using SharpCompress.Reader.Zip; using System; using System.IO; +using MediaBrowser.Common.IO; namespace MediaBrowser.Common.Implementations.Archiving { @@ -15,7 +16,14 @@ namespace MediaBrowser.Common.Implementations.Archiving /// public class ZipClient : IZipClient { - /// + private IFileSystem _fileSystem; + + public ZipClient(IFileSystem fileSystem) + { + _fileSystem = fileSystem; + } + + /// /// Extracts all. /// /// The source file. @@ -23,7 +31,7 @@ namespace MediaBrowser.Common.Implementations.Archiving /// if set to true [overwrite existing files]. public void ExtractAll(string sourceFile, string targetPath, bool overwriteExistingFiles) { - using (var fileStream = File.OpenRead(sourceFile)) + using (var fileStream = _fileSystem.OpenRead(sourceFile)) { ExtractAll(fileStream, targetPath, overwriteExistingFiles); } @@ -73,7 +81,7 @@ namespace MediaBrowser.Common.Implementations.Archiving /// if set to true [overwrite existing files]. public void ExtractAllFrom7z(string sourceFile, string targetPath, bool overwriteExistingFiles) { - using (var fileStream = File.OpenRead(sourceFile)) + using (var fileStream = _fileSystem.OpenRead(sourceFile)) { ExtractAllFrom7z(fileStream, targetPath, overwriteExistingFiles); } @@ -112,7 +120,7 @@ namespace MediaBrowser.Common.Implementations.Archiving /// if set to true [overwrite existing files]. public void ExtractAllFromTar(string sourceFile, string targetPath, bool overwriteExistingFiles) { - using (var fileStream = File.OpenRead(sourceFile)) + using (var fileStream = _fileSystem.OpenRead(sourceFile)) { ExtractAllFromTar(fileStream, targetPath, overwriteExistingFiles); } @@ -150,7 +158,7 @@ namespace MediaBrowser.Common.Implementations.Archiving /// if set to true [overwrite existing files]. public void ExtractAllFromRar(string sourceFile, string targetPath, bool overwriteExistingFiles) { - using (var fileStream = File.OpenRead(sourceFile)) + using (var fileStream = _fileSystem.OpenRead(sourceFile)) { ExtractAllFromRar(fileStream, targetPath, overwriteExistingFiles); } diff --git a/MediaBrowser.Common.Implementations/BaseApplicationHost.cs b/MediaBrowser.Common.Implementations/BaseApplicationHost.cs index bfd8c1f823..181f8e43d3 100644 --- a/MediaBrowser.Common.Implementations/BaseApplicationHost.cs +++ b/MediaBrowser.Common.Implementations/BaseApplicationHost.cs @@ -93,7 +93,7 @@ namespace MediaBrowser.Common.Implementations /// /// The _XML serializer /// - protected readonly IXmlSerializer XmlSerializer = new XmlSerializer(); + protected readonly IXmlSerializer XmlSerializer; /// /// Gets assemblies that failed to load @@ -180,7 +180,7 @@ namespace MediaBrowser.Common.Implementations { if (_deviceId == null) { - _deviceId = new DeviceId(ApplicationPaths, LogManager.GetLogger("SystemId")); + _deviceId = new DeviceId(ApplicationPaths, LogManager.GetLogger("SystemId"), FileSystemManager); } return _deviceId.Value; @@ -199,6 +199,7 @@ namespace MediaBrowser.Common.Implementations ILogManager logManager, IFileSystem fileSystem) { + XmlSerializer = new MediaBrowser.Common.Implementations.Serialization.XmlSerializer (fileSystem); FailedAssemblies = new List(); ApplicationPaths = applicationPaths; @@ -473,7 +474,7 @@ namespace MediaBrowser.Common.Implementations InstallationManager = new InstallationManager(Logger, this, ApplicationPaths, HttpClient, JsonSerializer, SecurityManager, ConfigurationManager, FileSystemManager); RegisterSingleInstance(InstallationManager); - ZipClient = new ZipClient(); + ZipClient = new ZipClient(FileSystemManager); RegisterSingleInstance(ZipClient); IsoManager = new IsoManager(); @@ -650,7 +651,7 @@ namespace MediaBrowser.Common.Implementations { try { - return Assembly.Load(File.ReadAllBytes((file))); + return Assembly.Load(FileSystemManager.ReadAllBytes((file))); } catch (Exception ex) { diff --git a/MediaBrowser.Common.Implementations/BaseApplicationPaths.cs b/MediaBrowser.Common.Implementations/BaseApplicationPaths.cs index 9ba2effd3a..f76359d30b 100644 --- a/MediaBrowser.Common.Implementations/BaseApplicationPaths.cs +++ b/MediaBrowser.Common.Implementations/BaseApplicationPaths.cs @@ -45,7 +45,7 @@ namespace MediaBrowser.Common.Implementations { _dataDirectory = Path.Combine(ProgramDataPath, "data"); - Directory.CreateDirectory(_dataDirectory); + FileSystem.CreateDirectory(_dataDirectory); } return _dataDirectory; @@ -152,7 +152,7 @@ namespace MediaBrowser.Common.Implementations { _cachePath = Path.Combine(ProgramDataPath, "cache"); - Directory.CreateDirectory(_cachePath); + FileSystem.CreateDirectory(_cachePath); } return _cachePath; diff --git a/MediaBrowser.Common.Implementations/Configuration/BaseConfigurationManager.cs b/MediaBrowser.Common.Implementations/Configuration/BaseConfigurationManager.cs index 1b9146644a..1e9d4c97ce 100644 --- a/MediaBrowser.Common.Implementations/Configuration/BaseConfigurationManager.cs +++ b/MediaBrowser.Common.Implementations/Configuration/BaseConfigurationManager.cs @@ -121,7 +121,7 @@ namespace MediaBrowser.Common.Implementations.Configuration { var path = CommonApplicationPaths.SystemConfigurationFilePath; - Directory.CreateDirectory(Path.GetDirectoryName(path)); + FileSystem.CreateDirectory(Path.GetDirectoryName(path)); lock (_configurationSyncLock) { @@ -276,7 +276,7 @@ namespace MediaBrowser.Common.Implementations.Configuration _configurations.AddOrUpdate(key, configuration, (k, v) => configuration); var path = GetConfigurationFile(key); - Directory.CreateDirectory(Path.GetDirectoryName(path)); + FileSystem.CreateDirectory(Path.GetDirectoryName(path)); lock (_configurationSyncLock) { diff --git a/MediaBrowser.Common.Implementations/Configuration/ConfigurationHelper.cs b/MediaBrowser.Common.Implementations/Configuration/ConfigurationHelper.cs index ff5b8bd599..6af59bb6b0 100644 --- a/MediaBrowser.Common.Implementations/Configuration/ConfigurationHelper.cs +++ b/MediaBrowser.Common.Implementations/Configuration/ConfigurationHelper.cs @@ -2,6 +2,7 @@ using System; using System.IO; using System.Linq; +using MediaBrowser.Common.IO; namespace MediaBrowser.Common.Implementations.Configuration { @@ -18,7 +19,7 @@ namespace MediaBrowser.Common.Implementations.Configuration /// The path. /// The XML serializer. /// System.Object. - public static object GetXmlConfiguration(Type type, string path, IXmlSerializer xmlSerializer) + public static object GetXmlConfiguration(Type type, string path, IXmlSerializer xmlSerializer, IFileSystem fileSystem) { object configuration; @@ -27,7 +28,7 @@ namespace MediaBrowser.Common.Implementations.Configuration // Use try/catch to avoid the extra file system lookup using File.Exists try { - buffer = File.ReadAllBytes(path); + buffer = fileSystem.ReadAllBytes(path); configuration = xmlSerializer.DeserializeFromBytes(type, buffer); } @@ -46,10 +47,10 @@ namespace MediaBrowser.Common.Implementations.Configuration // If the file didn't exist before, or if something has changed, re-save if (buffer == null || !buffer.SequenceEqual(newBytes)) { - Directory.CreateDirectory(Path.GetDirectoryName(path)); + fileSystem.CreateDirectory(Path.GetDirectoryName(path)); // Save it after load in case we got new items - File.WriteAllBytes(path, newBytes); + fileSystem.WriteAllBytes(path, newBytes); } return configuration; diff --git a/MediaBrowser.Common.Implementations/Devices/DeviceId.cs b/MediaBrowser.Common.Implementations/Devices/DeviceId.cs index 2a1c8877d7..02edc493a5 100644 --- a/MediaBrowser.Common.Implementations/Devices/DeviceId.cs +++ b/MediaBrowser.Common.Implementations/Devices/DeviceId.cs @@ -3,13 +3,15 @@ using MediaBrowser.Model.Logging; using System; using System.IO; using System.Text; +using MediaBrowser.Common.IO; namespace MediaBrowser.Common.Implementations.Devices { public class DeviceId { private readonly IApplicationPaths _appPaths; - private readonly ILogger _logger; + private readonly ILogger _logger; + private readonly IFileSystem _fileSystem; private readonly object _syncLock = new object(); @@ -24,7 +26,7 @@ namespace MediaBrowser.Common.Implementations.Devices { lock (_syncLock) { - var value = File.ReadAllText(CachePath, Encoding.UTF8); + var value = _fileSystem.ReadAllText(CachePath, Encoding.UTF8); Guid guid; if (Guid.TryParse(value, out guid)) @@ -55,11 +57,11 @@ namespace MediaBrowser.Common.Implementations.Devices { var path = CachePath; - Directory.CreateDirectory(Path.GetDirectoryName(path)); + _fileSystem.CreateDirectory(Path.GetDirectoryName(path)); lock (_syncLock) { - File.WriteAllText(path, id, Encoding.UTF8); + _fileSystem.WriteAllText(path, id, Encoding.UTF8); } } catch (Exception ex) @@ -88,10 +90,15 @@ namespace MediaBrowser.Common.Implementations.Devices private string _id; - public DeviceId(IApplicationPaths appPaths, ILogger logger) + public DeviceId(IApplicationPaths appPaths, ILogger logger, IFileSystem fileSystem) { + if (fileSystem == null) { + throw new ArgumentNullException ("fileSystem"); + } + _appPaths = appPaths; _logger = logger; + _fileSystem = fileSystem; } public string Value diff --git a/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs b/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs index 89f405e8a0..5dd1ab8080 100644 --- a/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs +++ b/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs @@ -355,7 +355,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager private async Task CacheResponse(HttpResponseInfo response, string responseCachePath) { - Directory.CreateDirectory(Path.GetDirectoryName(responseCachePath)); + _fileSystem.CreateDirectory(Path.GetDirectoryName(responseCachePath)); using (var responseStream = response.Content) { @@ -599,7 +599,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager { ValidateParams(options); - Directory.CreateDirectory(_appPaths.TempDirectory); + _fileSystem.CreateDirectory(_appPaths.TempDirectory); var tempFile = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid() + ".tmp"); diff --git a/MediaBrowser.Common.Implementations/IO/CommonFileSystem.cs b/MediaBrowser.Common.Implementations/IO/CommonFileSystem.cs index e9ef846634..5951dbb316 100644 --- a/MediaBrowser.Common.Implementations/IO/CommonFileSystem.cs +++ b/MediaBrowser.Common.Implementations/IO/CommonFileSystem.cs @@ -4,6 +4,8 @@ using MediaBrowser.Model.Logging; using System; using System.IO; using System.Text; +using System.Collections.Generic; +using System.Linq; namespace MediaBrowser.Common.Implementations.IO { @@ -75,7 +77,7 @@ namespace MediaBrowser.Common.Implementations.IO if (string.Equals(Path.GetExtension(filename), ".mblink", StringComparison.OrdinalIgnoreCase)) { - var path = File.ReadAllText(filename); + var path = ReadAllText(filename); return NormalizePath(path); } @@ -105,7 +107,7 @@ namespace MediaBrowser.Common.Implementations.IO throw new ArgumentNullException("target"); } - File.WriteAllText(shortcutPath, target); + _fileSystem.WriteAllText(shortcutPath, target); } /// @@ -230,7 +232,7 @@ namespace MediaBrowser.Common.Implementations.IO /// The share. /// if set to true [is asynchronous]. /// FileStream. - public FileStream GetFileStream(string path, FileMode mode, FileAccess access, FileShare share, bool isAsync = false) + public Stream GetFileStream(string path, FileMode mode, FileAccess access, FileShare share, bool isAsync = false) { if (_supportsAsyncFileStreams && isAsync) { @@ -264,11 +266,11 @@ namespace MediaBrowser.Common.Implementations.IO RemoveHiddenAttribute(file1); RemoveHiddenAttribute(file2); - File.Copy(file1, temp1, true); - File.Copy(file2, temp2, true); + CopyFile(file1, temp1, true); + CopyFile(file2, temp2, true); - File.Copy(temp1, file2, true); - File.Copy(temp2, file1, true); + CopyFile(temp1, file2, true); + CopyFile(temp2, file1, true); DeleteFile(temp1); DeleteFile(temp2); @@ -410,24 +412,42 @@ namespace MediaBrowser.Common.Implementations.IO //return Path.IsPathRooted(path); } - public void DeleteFile(string path, bool sendToRecycleBin) + public void DeleteFile(string path) { File.Delete(path); } - public void DeleteDirectory(string path, bool recursive, bool sendToRecycleBin) - { - Directory.Delete(path, recursive); - } - - public void DeleteFile(string path) - { - DeleteFile(path, false); - } - public void DeleteDirectory(string path, bool recursive) { - DeleteDirectory(path, recursive, false); - } + Directory.Delete(path, recursive); + } + + public void CreateDirectory(string path) + { + Directory.CreateDirectory(path); + } + + public IEnumerable GetDirectories(string path, bool recursive = false) + { + var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly; + + return new DirectoryInfo (path).EnumerateDirectories("*", searchOption); + } + + public IEnumerable GetFiles(string path, bool recursive = false) + { + var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly; + + return new DirectoryInfo (path).EnumerateFiles("*", searchOption); + } + + public IEnumerable GetFileSystemEntries(string path, bool recursive = false) + { + var directoryInfo = new DirectoryInfo (path); + var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly; + + return directoryInfo.EnumerateDirectories("*", searchOption) + .Concat(directoryInfo.EnumerateFiles("*", searchOption)); + } } } diff --git a/MediaBrowser.Common.Implementations/Logging/NlogManager.cs b/MediaBrowser.Common.Implementations/Logging/NlogManager.cs index 6d4cd06cb4..239ea03cda 100644 --- a/MediaBrowser.Common.Implementations/Logging/NlogManager.cs +++ b/MediaBrowser.Common.Implementations/Logging/NlogManager.cs @@ -208,7 +208,7 @@ namespace MediaBrowser.Common.Implementations.Logging { LogFilePath = Path.Combine(LogDirectory, LogFilePrefix + "-" + decimal.Round(DateTime.Now.Ticks / 10000000) + ".txt"); - Directory.CreateDirectory(Path.GetDirectoryName(LogFilePath)); + _fileSystem.CreateDirectory(Path.GetDirectoryName(LogFilePath)); AddFileTarget(LogFilePath, level); diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs index cbd1c1ac55..08c117220e 100644 --- a/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs +++ b/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs @@ -154,7 +154,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks _lastExecutionResult = value; var path = GetHistoryFilePath(); - Directory.CreateDirectory(Path.GetDirectoryName(path)); + _fileSystem.CreateDirectory(Path.GetDirectoryName(path)); lock (_lastExecutionResultSyncLock) { @@ -552,7 +552,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks { var path = GetConfigurationFilePath(); - Directory.CreateDirectory(Path.GetDirectoryName(path)); + _fileSystem.CreateDirectory(Path.GetDirectoryName(path)); JsonSerializer.SerializeToFile(triggers.Select(ScheduledTaskHelpers.GetTriggerInfo), path); } diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs index d9c178d8b5..6d5516ebd0 100644 --- a/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs +++ b/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs @@ -95,7 +95,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks /// The progress. private void DeleteCacheFilesFromDirectory(CancellationToken cancellationToken, string directory, DateTime minDateModified, IProgress progress) { - var filesToDelete = new DirectoryInfo(directory).EnumerateFiles("*", SearchOption.AllDirectories) + var filesToDelete = _fileSystem.GetFiles(directory, true) .Where(f => _fileSystem.GetLastWriteTimeUtc(f) < minDateModified) .ToList(); @@ -120,14 +120,14 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks progress.Report(100); } - private static void DeleteEmptyFolders(string parent) + private void DeleteEmptyFolders(string parent) { foreach (var directory in Directory.GetDirectories(parent)) { DeleteEmptyFolders(directory); if (!Directory.EnumerateFileSystemEntries(directory).Any()) { - Directory.Delete(directory, false); + _fileSystem.DeleteDirectory(directory, false); } } } diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs index b2759c52a6..ffba3d9dae 100644 --- a/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs +++ b/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs @@ -58,7 +58,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks // Delete log files more than n days old var minDateModified = DateTime.UtcNow.AddDays(-(ConfigurationManager.CommonConfiguration.LogFileRetentionDays)); - var filesToDelete = new DirectoryInfo(ConfigurationManager.CommonApplicationPaths.LogDirectoryPath).EnumerateFileSystemInfos("*", SearchOption.AllDirectories) + var filesToDelete = _fileSystem.GetFiles(ConfigurationManager.CommonApplicationPaths.LogDirectoryPath, true) .Where(f => _fileSystem.GetLastWriteTimeUtc(f) < minDateModified) .ToList(); diff --git a/MediaBrowser.Common.Implementations/Security/MBLicenseFile.cs b/MediaBrowser.Common.Implementations/Security/MBLicenseFile.cs index 63381efcdf..e5cf5856e7 100644 --- a/MediaBrowser.Common.Implementations/Security/MBLicenseFile.cs +++ b/MediaBrowser.Common.Implementations/Security/MBLicenseFile.cs @@ -99,15 +99,15 @@ namespace MediaBrowser.Common.Implementations.Security { try { - contents = File.ReadAllLines(licenseFile); + contents = _fileSystem.ReadAllLines(licenseFile); } catch (DirectoryNotFoundException) { - (File.Create(licenseFile)).Close(); + (_fileSystem.CreateFile(licenseFile)).Close(); } catch (FileNotFoundException) { - (File.Create(licenseFile)).Close(); + (_fileSystem.CreateFile(licenseFile)).Close(); } } if (contents != null && contents.Length > 0) @@ -150,8 +150,8 @@ namespace MediaBrowser.Common.Implementations.Security } var licenseFile = Filename; - Directory.CreateDirectory(Path.GetDirectoryName(licenseFile)); - lock (_fileLock) File.WriteAllLines(licenseFile, lines); + _fileSystem.CreateDirectory(Path.GetDirectoryName(licenseFile)); + lock (_fileLock) _fileSystem.WriteAllLines(licenseFile, lines); } } } diff --git a/MediaBrowser.Common.Implementations/Serialization/JsonSerializer.cs b/MediaBrowser.Common.Implementations/Serialization/JsonSerializer.cs index f194b334a8..80ccd72f77 100644 --- a/MediaBrowser.Common.Implementations/Serialization/JsonSerializer.cs +++ b/MediaBrowser.Common.Implementations/Serialization/JsonSerializer.cs @@ -53,7 +53,7 @@ namespace MediaBrowser.Common.Implementations.Serialization throw new ArgumentNullException("file"); } - using (Stream stream = File.Open(file, FileMode.Create)) + using (Stream stream = _fileSystem.GetFileStream(file, FileMode.Create, FileAccess.Write, FileShare.Read)) { SerializeToStream(obj, stream); } diff --git a/MediaBrowser.Common.Implementations/Serialization/XmlSerializer.cs b/MediaBrowser.Common.Implementations/Serialization/XmlSerializer.cs index 04030522f3..41a59fb2b4 100644 --- a/MediaBrowser.Common.Implementations/Serialization/XmlSerializer.cs +++ b/MediaBrowser.Common.Implementations/Serialization/XmlSerializer.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Concurrent; using System.IO; using System.Xml; +using MediaBrowser.Common.IO; namespace MediaBrowser.Common.Implementations.Serialization { @@ -11,6 +12,13 @@ namespace MediaBrowser.Common.Implementations.Serialization /// public class XmlSerializer : IXmlSerializer { + private IFileSystem _fileSystem; + + public XmlSerializer(IFileSystem fileSystem) + { + _fileSystem = fileSystem; + } + // Need to cache these // http://dotnetcodebox.blogspot.com/2013/01/xmlserializer-class-may-result-in.html private readonly ConcurrentDictionary _serializers = @@ -83,7 +91,7 @@ namespace MediaBrowser.Common.Implementations.Serialization /// System.Object. public object DeserializeFromFile(Type type, string file) { - using (var stream = File.OpenRead(file)) + using (var stream = _fileSystem.OpenRead(file)) { return DeserializeFromStream(type, stream); } diff --git a/MediaBrowser.Common.Implementations/Updates/InstallationManager.cs b/MediaBrowser.Common.Implementations/Updates/InstallationManager.cs index 5f205d69e7..fee23fd2e1 100644 --- a/MediaBrowser.Common.Implementations/Updates/InstallationManager.cs +++ b/MediaBrowser.Common.Implementations/Updates/InstallationManager.cs @@ -553,7 +553,7 @@ namespace MediaBrowser.Common.Implementations.Updates if (packageChecksum != Guid.Empty) // support for legacy uploads for now { using (var crypto = new MD5CryptoServiceProvider()) - using (var stream = new BufferedStream(File.OpenRead(tempFile), 100000)) + using (var stream = new BufferedStream(_fileSystem.OpenRead(tempFile), 100000)) { var check = Guid.Parse(BitConverter.ToString(crypto.ComputeHash(stream)).Replace("-", String.Empty)); if (check != packageChecksum) @@ -568,12 +568,12 @@ namespace MediaBrowser.Common.Implementations.Updates // Success - move it to the real target try { - Directory.CreateDirectory(Path.GetDirectoryName(target)); - File.Copy(tempFile, target, true); + _fileSystem.CreateDirectory(Path.GetDirectoryName(target)); + _fileSystem.CopyFile(tempFile, target, true); //If it is an archive - write out a version file so we know what it is if (isArchive) { - File.WriteAllText(target + ".ver", package.versionStr); + _fileSystem.WriteAllText(target + ".ver", package.versionStr); } } catch (IOException e) diff --git a/MediaBrowser.Common/IO/IFileSystem.cs b/MediaBrowser.Common/IO/IFileSystem.cs index 5ce84f4360..60ba4c8aef 100644 --- a/MediaBrowser.Common/IO/IFileSystem.cs +++ b/MediaBrowser.Common/IO/IFileSystem.cs @@ -1,5 +1,7 @@ using System; using System.IO; +using System.Collections.Generic; +using System.Text; namespace MediaBrowser.Common.IO { @@ -73,7 +75,9 @@ namespace MediaBrowser.Common.IO /// The share. /// if set to true [is asynchronous]. /// FileStream. - FileStream GetFileStream(string path, FileMode mode, FileAccess access, FileShare share, bool isAsync = false); + Stream GetFileStream(string path, FileMode mode, FileAccess access, FileShare share, bool isAsync = false); + + Stream OpenRead(String path); /// /// Swaps the files. @@ -134,21 +138,6 @@ namespace MediaBrowser.Common.IO /// true if [is path file] [the specified path]; otherwise, false. bool IsPathFile(string path); - /// - /// Deletes the file. - /// - /// The path. - /// if set to true [send to recycle bin]. - void DeleteFile(string path, bool sendToRecycleBin); - - /// - /// Deletes the directory. - /// - /// The path. - /// if set to true [recursive]. - /// if set to true [send to recycle bin]. - void DeleteDirectory(string path, bool recursive, bool sendToRecycleBin); - /// /// Deletes the file. /// @@ -161,5 +150,41 @@ namespace MediaBrowser.Common.IO /// The path. /// if set to true [recursive]. void DeleteDirectory(string path, bool recursive); + + IEnumerable GetDirectories(string path, bool recursive = false); + + IEnumerable GetFiles(string path, bool recursive = false); + + IEnumerable GetFileSystemEntries(string path, bool recursive = false); + + void CreateDirectory(string path); + + void CopyFile(string source, string target, bool overwrite); + + void MoveFile(string source, string target); + + void MoveDirectory(string source, string target); + + bool DirectoryExists(string path); + + bool FileExists(string path); + + string ReadAllText(string path, Encoding encoding); + + string ReadAllText(string path); + + byte[] ReadAllBytes(string path); + + void WriteAllBytes(string path, byte[] bytes); + + void WriteAllText(string path, string text, Encoding encoding); + + void WriteAllText(string path, string text); + + void CreateFile(string path); + + void WriteAllLines(string path, string[] lines); + + string[] ReadAllLines(string path); } } diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 54267490df..25e742e7cc 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -683,7 +683,7 @@ namespace MediaBrowser.Controller.Entities { var files = fileSystemChildren.OfType() .Where(i => string.Equals(i.Name, ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase)) - .SelectMany(i => i.EnumerateFiles("*", SearchOption.TopDirectoryOnly)) + .SelectMany(i => directoryService.GetFiles(i.FullName)) .ToList(); // Support plex/xbmc convention @@ -719,7 +719,7 @@ namespace MediaBrowser.Controller.Entities { var files = fileSystemChildren.OfType() .Where(i => string.Equals(i.Name, ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase)) - .SelectMany(i => i.EnumerateFiles("*", SearchOption.TopDirectoryOnly)); + .SelectMany(i => directoryService.GetFiles(i.FullName)); return LibraryManager.ResolvePaths(files, directoryService, null) .OfType