Browse Source

Don't append transcodes to transcoding temp path

Bond-009 5 years ago
parent
commit
d4b438791f

+ 2 - 4
Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs

@@ -4,7 +4,6 @@ using System.Collections.Generic;
 using System.Globalization;
 using System.IO;
 using System.Linq;
-using System.Threading;
 using MediaBrowser.Common.Configuration;
 using MediaBrowser.Common.Events;
 using MediaBrowser.Common.Extensions;
@@ -16,7 +15,7 @@ using Microsoft.Extensions.Logging;
 namespace Emby.Server.Implementations.AppBase
 {
     /// <summary>
-    /// Class BaseConfigurationManager
+    /// Class BaseConfigurationManager.
     /// </summary>
     public abstract class BaseConfigurationManager : IConfigurationManager
     {
@@ -314,8 +313,7 @@ namespace Emby.Server.Implementations.AppBase
                 throw new ArgumentException("Expected configuration type is " + configurationType.Name);
             }
 
-            var validatingStore = configurationStore as IValidatingConfiguration;
-            if (validatingStore != null)
+            if (configurationStore is IValidatingConfiguration validatingStore)
             {
                 var currentConfiguration = GetConfiguration(key);
 

+ 2 - 3
Emby.Server.Implementations/ApplicationHost.cs

@@ -88,7 +88,6 @@ using MediaBrowser.Model.Cryptography;
 using MediaBrowser.Model.Diagnostics;
 using MediaBrowser.Model.Dlna;
 using MediaBrowser.Model.Events;
-using MediaBrowser.Model.Extensions;
 using MediaBrowser.Model.Globalization;
 using MediaBrowser.Model.IO;
 using MediaBrowser.Model.MediaInfo;
@@ -110,7 +109,6 @@ using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Http.Extensions;
 using Microsoft.Extensions.Configuration;
 using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.DependencyInjection.Extensions;
 using Microsoft.Extensions.Logging;
 using ServiceStack;
 using OperatingSystem = MediaBrowser.Common.System.OperatingSystem;
@@ -1424,6 +1422,7 @@ namespace Emby.Server.Implementations
         public async Task<SystemInfo> GetSystemInfo(CancellationToken cancellationToken)
         {
             var localAddress = await GetLocalApiUrl(cancellationToken).ConfigureAwait(false);
+            var transcodingTempPath = ConfigurationManager.GetTranscodePath();
 
             return new SystemInfo
             {
@@ -1447,7 +1446,7 @@ namespace Emby.Server.Implementations
                 CanSelfRestart = CanSelfRestart,
                 CanLaunchWebBrowser = CanLaunchWebBrowser,
                 HasUpdateAvailable = HasUpdateAvailable,
-                TranscodingTempPath = ApplicationPaths.TranscodePath,
+                TranscodingTempPath = transcodingTempPath,
                 ServerName = FriendlyName,
                 LocalAddress = localAddress,
                 SupportsLibraryMonitor = true,

+ 1 - 32
Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs

@@ -1,5 +1,4 @@
 using System;
-using System.Collections.Generic;
 using System.IO;
 using Emby.Server.Implementations.AppBase;
 using MediaBrowser.Common.Configuration;
@@ -14,7 +13,7 @@ using Microsoft.Extensions.Logging;
 namespace Emby.Server.Implementations.Configuration
 {
     /// <summary>
-    /// Class ServerConfigurationManager
+    /// Class ServerConfigurationManager.
     /// </summary>
     public class ServerConfigurationManager : BaseConfigurationManager, IServerConfigurationManager
     {
@@ -62,13 +61,6 @@ namespace Emby.Server.Implementations.Configuration
             base.OnConfigurationUpdated();
         }
 
-        public override void AddParts(IEnumerable<IConfigurationFactory> factories)
-        {
-            base.AddParts(factories);
-
-            UpdateTranscodePath();
-        }
-
         /// <summary>
         /// Updates the metadata path.
         /// </summary>
@@ -84,28 +76,6 @@ namespace Emby.Server.Implementations.Configuration
             }
         }
 
-        /// <summary>
-        /// Updates the transcoding temporary path.
-        /// </summary>
-        private void UpdateTranscodePath()
-        {
-            var encodingConfig = this.GetConfiguration<EncodingOptions>("encoding");
-
-            ((ServerApplicationPaths)ApplicationPaths).TranscodePath = string.IsNullOrEmpty(encodingConfig.TranscodingTempPath) ?
-                null :
-                Path.Combine(encodingConfig.TranscodingTempPath, "transcodes");
-        }
-
-        protected override void OnNamedConfigurationUpdated(string key, object configuration)
-        {
-            base.OnNamedConfigurationUpdated(key, configuration);
-
-            if (string.Equals(key, "encoding", StringComparison.OrdinalIgnoreCase))
-            {
-                UpdateTranscodePath();
-            }
-        }
-
         /// <summary>
         /// Replaces the configuration.
         /// </summary>
@@ -123,7 +93,6 @@ namespace Emby.Server.Implementations.Configuration
             base.ReplaceConfiguration(newConfiguration);
         }
 
-
         /// <summary>
         /// Validates the SSL certificate.
         /// </summary>

+ 3 - 4
Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs

@@ -582,11 +582,10 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
                     modelInfo.TunerCount,
                     FileSystem,
                     Logger,
-                    Config.ApplicationPaths,
+                    Config,
                     _appHost,
                     _networkManager,
                     _streamHelper);
-
             }
 
             var enableHttpStream = true;
@@ -611,7 +610,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
                     FileSystem,
                     _httpClient,
                     Logger,
-                    Config.ApplicationPaths,
+                    Config,
                     _appHost,
                     _streamHelper);
             }
@@ -624,7 +623,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
                 modelInfo.TunerCount,
                 FileSystem,
                 Logger,
-                Config.ApplicationPaths,
+                Config,
                 _appHost,
                 _networkManager,
                 _streamHelper);

+ 3 - 2
Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs

@@ -6,6 +6,7 @@ using System.Net.Sockets;
 using System.Threading;
 using System.Threading.Tasks;
 using MediaBrowser.Common.Net;
+using MediaBrowser.Common.Configuration;
 using MediaBrowser.Controller;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Model.Dto;
@@ -33,11 +34,11 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
             int numTuners,
             IFileSystem fileSystem,
             ILogger logger,
-            IServerApplicationPaths appPaths,
+            IConfigurationManager configurationManager,
             IServerApplicationHost appHost,
             INetworkManager networkManager,
             IStreamHelper streamHelper)
-            : base(mediaSource, tunerHostInfo, fileSystem, logger, appPaths, streamHelper)
+            : base(mediaSource, tunerHostInfo, fileSystem, logger, configurationManager, streamHelper)
         {
             _appHost = appHost;
             _networkManager = networkManager;

+ 7 - 5
Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs

@@ -5,8 +5,8 @@ using System.IO;
 using System.Linq;
 using System.Threading;
 using System.Threading.Tasks;
-using MediaBrowser.Controller;
 using MediaBrowser.Controller.Library;
+using MediaBrowser.Common.Configuration;
 using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.IO;
 using MediaBrowser.Model.LiveTv;
@@ -16,8 +16,10 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
 {
     public class LiveStream : ILiveStream
     {
+        private readonly IConfigurationManager _configurationManager;
+
         protected readonly IFileSystem FileSystem;
-        protected readonly IServerApplicationPaths AppPaths;
+
         protected readonly IStreamHelper StreamHelper;
 
         protected string TempFilePath;
@@ -29,7 +31,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
             TunerHostInfo tuner,
             IFileSystem fileSystem,
             ILogger logger,
-            IServerApplicationPaths appPaths,
+            IConfigurationManager configurationManager,
             IStreamHelper streamHelper)
         {
             OriginalMediaSource = mediaSource;
@@ -44,7 +46,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
                 TunerHostId = tuner.Id;
             }
 
-            AppPaths = appPaths;
+            _configurationManager = configurationManager;
             StreamHelper = streamHelper;
 
             ConsumerCount = 1;
@@ -68,7 +70,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
 
         protected void SetTempFilePath(string extension)
         {
-            TempFilePath = Path.Combine(AppPaths.GetTranscodePath(), UniqueId + "." + extension);
+            TempFilePath = Path.Combine(_configurationManager.GetTranscodePath(), UniqueId + "." + extension);
         }
 
         public virtual Task Open(CancellationToken openCancellationToken)

+ 2 - 2
Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs

@@ -114,11 +114,11 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
 
                 if (!_disallowedSharedStreamExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
                 {
-                    return new SharedHttpStream(mediaSource, info, streamId, FileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost, _streamHelper);
+                    return new SharedHttpStream(mediaSource, info, streamId, FileSystem, _httpClient, Logger, Config, _appHost, _streamHelper);
                 }
             }
 
-            return new LiveStream(mediaSource, info, FileSystem, Logger, Config.ApplicationPaths, _streamHelper);
+            return new LiveStream(mediaSource, info, FileSystem, Logger, Config, _streamHelper);
         }
 
         public async Task Validate(TunerHostInfo info)

+ 3 - 2
Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs

@@ -3,6 +3,7 @@ using System.Collections.Generic;
 using System.IO;
 using System.Threading;
 using System.Threading.Tasks;
+using MediaBrowser.Common.Configuration;
 using MediaBrowser.Common.Net;
 using MediaBrowser.Controller;
 using MediaBrowser.Controller.Library;
@@ -26,10 +27,10 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
             IFileSystem fileSystem,
             IHttpClient httpClient,
             ILogger logger,
-            IServerApplicationPaths appPaths,
+            IConfigurationManager configurationManager,
             IServerApplicationHost appHost,
             IStreamHelper streamHelper)
-            : base(mediaSource, tunerHostInfo, fileSystem, logger, appPaths, streamHelper)
+            : base(mediaSource, tunerHostInfo, fileSystem, logger, configurationManager, streamHelper)
         {
             _httpClient = httpClient;
             _appHost = appHost;

+ 5 - 17
Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs

@@ -4,6 +4,7 @@ using System.IO;
 using System.Linq;
 using System.Threading;
 using System.Threading.Tasks;
+using MediaBrowser.Common.Configuration;
 using MediaBrowser.Model.IO;
 using MediaBrowser.Model.Tasks;
 using Microsoft.Extensions.Logging;
@@ -15,24 +16,18 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
     /// </summary>
     public class DeleteTranscodeFileTask : IScheduledTask, IConfigurableScheduledTask
     {
-        /// <summary>
-        /// Gets or sets the application paths.
-        /// </summary>
-        /// <value>The application paths.</value>
-        private ServerApplicationPaths ApplicationPaths { get; set; }
-
         private readonly ILogger _logger;
-
+        private readonly IConfigurationManager _configurationManager;
         private readonly IFileSystem _fileSystem;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="DeleteTranscodeFileTask" /> class.
         /// </summary>
-        public DeleteTranscodeFileTask(ServerApplicationPaths appPaths, ILogger logger, IFileSystem fileSystem)
+        public DeleteTranscodeFileTask(ILogger logger, IFileSystem fileSystem, IConfigurationManager configurationManager)
         {
-            ApplicationPaths = appPaths;
             _logger = logger;
             _fileSystem = fileSystem;
+            _configurationManager = configurationManager;
         }
 
         /// <summary>
@@ -52,14 +47,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
             var minDateModified = DateTime.UtcNow.AddDays(-1);
             progress.Report(50);
 
-            try
-            {
-                DeleteTempFilesFromDirectory(cancellationToken, ApplicationPaths.TranscodePath, minDateModified, progress);
-            }
-            catch (DirectoryNotFoundException)
-            {
-                // No biggie here. Nothing to delete
-            }
+            DeleteTempFilesFromDirectory(cancellationToken, _configurationManager.GetTranscodingTempPath(), minDateModified, progress);
 
             return Task.CompletedTask;
         }

+ 0 - 34
Emby.Server.Implementations/ServerApplicationPaths.cs

@@ -107,40 +107,6 @@ namespace Emby.Server.Implementations
         /// <value>The user configuration directory path.</value>
         public string UserConfigurationDirectoryPath => Path.Combine(ConfigurationDirectoryPath, "users");
 
-        public string DefaultTranscodePath => _defaultTranscodePath ?? (_defaultTranscodePath = Path.Combine(ProgramDataPath, "transcodes"));
-
-        public string TranscodePath
-        {
-            get => _transcodePath ?? (_transcodePath = DefaultTranscodePath);
-            set => _transcodePath = value;
-        }
-
-        public string GetTranscodePath()
-        {
-            var path = TranscodePath;
-
-            if (!string.Equals(path, DefaultTranscodePath, StringComparison.OrdinalIgnoreCase))
-            {
-                try
-                {
-                    Directory.CreateDirectory(path);
-
-                    var testPath = Path.Combine(path, Guid.NewGuid().ToString());
-                    Directory.CreateDirectory(testPath);
-                    Directory.Delete(testPath);
-
-                    return path;
-                }
-                catch
-                {
-                }
-            }
-
-            path = DefaultTranscodePath;
-            Directory.CreateDirectory(path);
-            return path;
-        }
-
         public string InternalMetadataPath
         {
             get => _internalMetadataPath ?? (_internalMetadataPath = Path.Combine(DataPath, "metadata"));

+ 1 - 7
MediaBrowser.Api/ApiEntryPoint.cs

@@ -13,7 +13,6 @@ using MediaBrowser.Controller.MediaEncoding;
 using MediaBrowser.Controller.Net;
 using MediaBrowser.Controller.Plugins;
 using MediaBrowser.Controller.Session;
-using MediaBrowser.Model.Configuration;
 using MediaBrowser.Model.Diagnostics;
 using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.IO;
@@ -157,17 +156,12 @@ namespace MediaBrowser.Api
             return Task.CompletedTask;
         }
 
-        public EncodingOptions GetEncodingOptions()
-        {
-            return ConfigurationManagerExtensions.GetConfiguration<EncodingOptions>(ConfigurationManager, "encoding");
-        }
-
         /// <summary>
         /// Deletes the encoded media cache.
         /// </summary>
         private void DeleteEncodedMediaCache()
         {
-            var path = ConfigurationManager.ApplicationPaths.GetTranscodePath();
+            var path = ConfigurationManager.GetTranscodePath();
 
             if (!Directory.Exists(path))
             {

+ 4 - 3
MediaBrowser.Api/Playback/BaseStreamingService.cs

@@ -7,6 +7,7 @@ using System.Linq;
 using System.Text;
 using System.Threading;
 using System.Threading.Tasks;
+using MediaBrowser.Common.Configuration;
 using MediaBrowser.Common.Extensions;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Devices;
@@ -141,7 +142,7 @@ namespace MediaBrowser.Api.Playback
 
             var filename = data.GetMD5().ToString("N", CultureInfo.InvariantCulture);
             var ext = outputFileExtension.ToLowerInvariant();
-            var folder = ServerConfigurationManager.ApplicationPaths.TranscodePath;
+            var folder = ServerConfigurationManager.GetTranscodePath();
 
             if (EnableOutputInSubFolder)
             {
@@ -215,7 +216,7 @@ namespace MediaBrowser.Api.Playback
                 }
             }
 
-            var encodingOptions = ApiEntryPoint.Instance.GetEncodingOptions();
+            var encodingOptions = ServerConfigurationManager.GetEncodingOptions();
 
             var process = new Process()
             {
@@ -845,7 +846,7 @@ namespace MediaBrowser.Api.Playback
                 ? GetOutputFileExtension(state)
                 : ('.' + state.OutputContainer);
 
-            var encodingOptions = ApiEntryPoint.Instance.GetEncodingOptions();
+            var encodingOptions = ServerConfigurationManager.GetEncodingOptions();
 
             state.OutputFilePath = GetOutputFilePath(state, encodingOptions, ext);
 

+ 5 - 8
MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs

@@ -2,7 +2,7 @@ using System;
 using System.IO;
 using System.Linq;
 using System.Threading.Tasks;
-using MediaBrowser.Controller;
+using MediaBrowser.Common.Configuration;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.MediaEncoding;
 using MediaBrowser.Controller.Net;
@@ -83,13 +83,11 @@ namespace MediaBrowser.Api.Playback.Hls
 
     public class HlsSegmentService : BaseApiService
     {
-        private readonly IServerApplicationPaths _appPaths;
         private readonly IServerConfigurationManager _config;
         private readonly IFileSystem _fileSystem;
 
-        public HlsSegmentService(IServerApplicationPaths appPaths, IServerConfigurationManager config, IFileSystem fileSystem)
+        public HlsSegmentService(IServerConfigurationManager config, IFileSystem fileSystem)
         {
-            _appPaths = appPaths;
             _config = config;
             _fileSystem = fileSystem;
         }
@@ -97,7 +95,7 @@ namespace MediaBrowser.Api.Playback.Hls
         public Task<object> Get(GetHlsPlaylistLegacy request)
         {
             var file = request.PlaylistId + Path.GetExtension(Request.PathInfo);
-            file = Path.Combine(_appPaths.TranscodePath, file);
+            file = Path.Combine(_config.GetTranscodePath(), file);
 
             return GetFileResult(file, file);
         }
@@ -115,8 +113,7 @@ namespace MediaBrowser.Api.Playback.Hls
         public Task<object> Get(GetHlsVideoSegmentLegacy request)
         {
             var file = request.SegmentId + Path.GetExtension(Request.PathInfo);
-
-            var transcodeFolderPath = _config.ApplicationPaths.TranscodePath;
+            var transcodeFolderPath = _config.GetTranscodePath();
             file = Path.Combine(transcodeFolderPath, file);
 
             var normalizedPlaylistId = request.PlaylistId;
@@ -136,7 +133,7 @@ namespace MediaBrowser.Api.Playback.Hls
         {
             // TODO: Deprecate with new iOS app
             var file = request.SegmentId + Path.GetExtension(Request.PathInfo);
-            file = Path.Combine(_appPaths.TranscodePath, file);
+            file = Path.Combine(_config.GetTranscodePath(), file);
 
             return ResultFactory.GetStaticFileResult(Request, file, FileShareMode.ReadWrite);
         }

+ 28 - 0
MediaBrowser.Common/Configuration/EncodingConfigurationExtensions.cs

@@ -0,0 +1,28 @@
+using System.IO;
+using MediaBrowser.Model.Configuration;
+
+namespace MediaBrowser.Common.Configuration
+{
+    /// <summary>
+    /// Class containing extension methods for working with the encoding configuration.
+    /// </summary>
+    public static class EncodingConfigurationExtensions
+    {
+        /// <summary>
+        /// Gets the encoding options.
+        /// </summary>
+        /// <param name="configurationManager">The configuration manager.</param>
+        /// <returns>The encoding options.</returns>
+        public static EncodingOptions GetEncodingOptions(this IConfigurationManager configurationManager)
+            => configurationManager.GetConfiguration<EncodingOptions>("encoding");
+
+        /// <summary>
+        /// Retrieves the transcoding temp path from the encoding configuration.
+        /// </summary>
+        /// <param name="configurationManager">The Configuration manager.</param>
+        /// <returns>The transcoding temp path.</returns>
+        public static string GetTranscodePath(this IConfigurationManager configurationManager)
+            => configurationManager.GetEncodingOptions().TranscodingTempPath
+                ?? Path.Combine(configurationManager.CommonApplicationPaths.ProgramDataPath, "transcoding-temp");
+    }
+}

+ 0 - 8
MediaBrowser.Controller/IServerApplicationPaths.cs

@@ -82,12 +82,6 @@ namespace MediaBrowser.Controller
         /// <value>The user configuration directory path.</value>
         string UserConfigurationDirectoryPath { get; }
 
-        /// <summary>
-        /// Gets the transcoding temporary path.
-        /// </summary>
-        /// <value>The transcoding temporary path.</value>
-        string TranscodePath { get; }
-
         /// <summary>
         /// Gets the internal metadata path.
         /// </summary>
@@ -96,7 +90,5 @@ namespace MediaBrowser.Controller
         string VirtualInternalMetadataPath { get; }
 
         string ArtistsPath { get; }
-
-        string GetTranscodePath();
     }
 }

+ 0 - 1
MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs

@@ -10,7 +10,6 @@ using MediaBrowser.Model.Configuration;
 using MediaBrowser.Model.Dlna;
 using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Extensions;
 using MediaBrowser.Model.IO;
 using MediaBrowser.Model.MediaInfo;
 

+ 11 - 19
MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationFactory.cs

@@ -1,54 +1,46 @@
+using System;
 using System.Collections.Generic;
+using System.Globalization;
 using System.IO;
 using MediaBrowser.Common.Configuration;
 using MediaBrowser.Model.Configuration;
-using MediaBrowser.Model.IO;
 
 namespace MediaBrowser.MediaEncoding.Configuration
 {
     public class EncodingConfigurationFactory : IConfigurationFactory
     {
-        private readonly IFileSystem _fileSystem;
-
-        public EncodingConfigurationFactory(IFileSystem fileSystem)
-        {
-            _fileSystem = fileSystem;
-        }
-
         public IEnumerable<ConfigurationStore> GetConfigurations()
         {
             return new[]
             {
-                new EncodingConfigurationStore(_fileSystem)
+                new EncodingConfigurationStore()
             };
         }
     }
 
     public class EncodingConfigurationStore : ConfigurationStore, IValidatingConfiguration
     {
-        private readonly IFileSystem _fileSystem;
-
-        public EncodingConfigurationStore(IFileSystem fileSystem)
+        public EncodingConfigurationStore()
         {
             ConfigurationType = typeof(EncodingOptions);
             Key = "encoding";
-            _fileSystem = fileSystem;
         }
 
         public void Validate(object oldConfig, object newConfig)
         {
-            var oldEncodingConfig = (EncodingOptions)oldConfig;
-            var newEncodingConfig = (EncodingOptions)newConfig;
-
-            var newPath = newEncodingConfig.TranscodingTempPath;
+            var newPath = ((EncodingOptions)newConfig).TranscodingTempPath;
 
             if (!string.IsNullOrWhiteSpace(newPath)
-                && !string.Equals(oldEncodingConfig.TranscodingTempPath ?? string.Empty, newPath))
+                && !string.Equals(((EncodingOptions)oldConfig).TranscodingTempPath, newPath, StringComparison.Ordinal))
             {
                 // Validate
                 if (!Directory.Exists(newPath))
                 {
-                    throw new FileNotFoundException(string.Format("{0} does not exist.", newPath));
+                    throw new DirectoryNotFoundException(
+                        string.Format(
+                            CultureInfo.InvariantCulture,
+                            "{0} does not exist.",
+                            newPath));
                 }
             }
         }