diff --git a/src/ConfigSettings/Settings/AppConfig.cs b/src/ConfigSettings/Settings/AppConfig.cs index 638ec65..99f323d 100644 --- a/src/ConfigSettings/Settings/AppConfig.cs +++ b/src/ConfigSettings/Settings/AppConfig.cs @@ -35,7 +35,17 @@ private static string AppConfigFilePath /// Экземпляр класса. Также создаёт новый конфиг согласно правилам. public static AppConfig Change() { - var liveConfigPath = ChangeConfig.Execute(AppConfigFilePath); + return Change(null); + } + + /// + /// Сменить имя. + /// + /// Функция разрешения пути до папки в appdata, когда флаг forceReturnAppDataPath включен. + /// Экземпляр класса. Также создаёт новый конфиг согласно правилам. + public static AppConfig Change(Func resolveForcedAppDataPath) + { + var liveConfigPath = ChangeConfig.Execute(AppConfigFilePath, resolveForcedAppDataPath); return new ChangeAppConfig(liveConfigPath); } diff --git a/src/ConfigSettings/Settings/ChangeConfig.cs b/src/ConfigSettings/Settings/ChangeConfig.cs index 43f2291..a0f5a43 100644 --- a/src/ConfigSettings/Settings/ChangeConfig.cs +++ b/src/ConfigSettings/Settings/ChangeConfig.cs @@ -3,9 +3,8 @@ using System.IO; using System.Linq; using System.Xml.Linq; -using ConfigSettings.Utils; -using ConfigSettings.Internal; using ConfigSettings.Patch; +using ConfigSettings.Utils; namespace ConfigSettings { @@ -158,7 +157,7 @@ public static bool IsFileLocked(string filePath) /// Путь к реальному (live) файлу-конфигу. public static string GetLiveConfigFilePath(string currentConfigPath) { - return GetLiveConfigFilePath(currentConfigPath, false); + return GetLiveConfigFilePath(currentConfigPath, false, null); } /// @@ -166,8 +165,9 @@ public static string GetLiveConfigFilePath(string currentConfigPath) /// /// Путь к оригинальному файлу-конфигу. /// Принудительно возвращать путь к appdata. + /// Функция разрешения пути до папки в appdata, когда флаг forceReturnAppDataPath включен. /// Путь к реальному (live) файлу-конфигу. - private static string GetLiveConfigFilePath(string currentConfigPath, bool forceReturnAppDataPath) + private static string GetLiveConfigFilePath(string currentConfigPath, bool forceReturnAppDataPath, Func resolveForcedAppDataPath) { var nameWithoutExt = Path.GetFileNameWithoutExtension(currentConfigPath); var liveConfigName = nameWithoutExt + ".live" + Path.GetExtension(currentConfigPath); @@ -177,9 +177,14 @@ private static string GetLiveConfigFilePath(string currentConfigPath, bool force if (!IsFileLocked(liveConfigBesideCurrent)) return liveConfigBesideCurrent; } - var appDataPath = Path.Combine(SpecialFolders.ProductUserApplicationData("Configs", - Path.GetDirectoryName(currentConfigPath).GetMD5Hash().Substring(0, 8)), liveConfigName); - return appDataPath; + + if (resolveForcedAppDataPath == null) + throw new ArgumentNullException(nameof(resolveForcedAppDataPath), "Remove FORCE_USE_APPDATA_PATH meta tag or specify resolveForcedAppDataPath function on ChangeConfig.Execute"); + + var appDataPath = resolveForcedAppDataPath(currentConfigPath); + if (!Directory.Exists(appDataPath)) + Directory.CreateDirectory(appDataPath); + return Path.Combine(appDataPath, liveConfigName); } /// @@ -189,7 +194,18 @@ private static string GetLiveConfigFilePath(string currentConfigPath, bool force /// Путь к измененному конфигу. public static string Execute(string currentConfigPath) { - return Execute(currentConfigPath, null); + return Execute(currentConfigPath, null, null); + } + + /// + /// Выполнить изменение конфига на основе правил. + /// + /// Путь к текущем конфигу. + /// Функция разрешения пути до папки в appdata, когда указан мета тег FORCE_USE_APPDATA_PATH. + /// Путь к измененному конфигу. + public static string Execute(string currentConfigPath, Func resolveForcedAppDataPath) + { + return Execute(currentConfigPath, null, resolveForcedAppDataPath); } /// @@ -199,6 +215,18 @@ public static string Execute(string currentConfigPath) /// Имя файла с настройками конфига. /// Путь к измененному конфигу. public static string Execute(string currentConfigPath, string settingsFileName) + { + return Execute(currentConfigPath, settingsFileName, null); + } + + /// + /// Выполнить изменение конфига на основе правил. + /// + /// Путь к текущем конфигу. + /// Имя файла с настройками конфига. + /// Функция разрешения пути до папки в appdata, когда флаг forceReturnAppDataPath включен. + /// Путь к измененному конфигу. + public static string Execute(string currentConfigPath, string settingsFileName, Func resolveForcedAppDataPath) { lock (lockInstance) { @@ -212,7 +240,7 @@ public static string Execute(string currentConfigPath, string settingsFileName) var liveConfigPath = parser.HasMetaVariable(ForceUseAppDataPathMetaVariable) && bool.TryParse(parser.GetMetaVariableValue(ForceUseAppDataPathMetaVariable), out forceUseAppDataPath) - ? GetLiveConfigFilePath(currentConfigPath, forceUseAppDataPath) + ? GetLiveConfigFilePath(currentConfigPath, forceUseAppDataPath, resolveForcedAppDataPath) : GetLiveConfigFilePath(currentConfigPath); if (HasGeneratedBlock(config) && File.Exists(liveConfigPath)) ReplaceConfigWithoutGeneratedBlocks(config, liveConfigPath); diff --git a/src/ConfigSettings/Settings/SpecialFolders.cs b/src/ConfigSettings/Settings/SpecialFolders.cs deleted file mode 100644 index 707bd57..0000000 --- a/src/ConfigSettings/Settings/SpecialFolders.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using System.IO; -using System.Reflection; -using ConfigSettings.Utils; - -namespace ConfigSettings.Internal -{ - /// - /// Класс предопределенных специальных папок платформы. - /// - public static class SpecialFolders - { - #region Поля и свойства - - /// - /// Информация о продукте для главной сборки. - /// - private static readonly Lazy mainAssemblyProductInfo = new Lazy(() => new AssemblyProductInfo(Assembly.GetEntryAssembly() ?? Assembly.GetExecutingAssembly())); - - #endregion - - #region Методы - - /// - /// Создать и вернуть подпапку в папке продукта профиля пользователя. - /// - /// Информация о продукте. - /// Путь к подпапкам. - /// Папка. - public static string ProductUserApplicationData(AssemblyProductInfo productInfo, params string[] subpath) - { - var subpaths = Path.Combine(subpath); - return Directory.CreateDirectory(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), productInfo.CompanyName, productInfo.NormalizedProductName, subpaths)).FullName; - } - - /// - /// Создать и вернуть подпапку в папке продукта профиля пользователя. - /// - /// Путь к подпапкам. - /// Папка. - public static string ProductUserApplicationData(params string[] subpath) - { - return ProductUserApplicationData(mainAssemblyProductInfo.Value, subpath); - } - - #endregion - } -} diff --git a/src/ConfigSettings/Utils/AssemblyProductInfo.cs b/src/ConfigSettings/Utils/AssemblyProductInfo.cs deleted file mode 100644 index ecc4183..0000000 --- a/src/ConfigSettings/Utils/AssemblyProductInfo.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Linq; -using System.Reflection; - -namespace ConfigSettings.Utils -{ - /// - /// Информация о продукте. - /// - public class AssemblyProductInfo - { - /// - /// Имя компании. - /// - public string CompanyName { get; } - - /// - /// Имя продукта. - /// - public string ProductName { get; } - - /// - /// Нормализованное (без пробелов) имя продукта. - /// - public string NormalizedProductName => this.ProductName.Replace(" ", string.Empty); - - /// - /// Конструктор по умолчанию. - /// - /// Сборка, содержащая информацию о продукте. - public AssemblyProductInfo(Assembly assemblyWithInfo) - { - var customAttributesData = assemblyWithInfo.GetCustomAttributesData(); - this.CompanyName = (string)customAttributesData.Single(ca => ca.AttributeType == typeof(AssemblyCompanyAttribute)).ConstructorArguments.Single().Value; - this.ProductName = (string)customAttributesData.Single(ca => ca.AttributeType == typeof(AssemblyProductAttribute)).ConstructorArguments.Single().Value; - } - } -} diff --git a/src/Tests/AssemblyProductInfoTests.cs b/src/Tests/AssemblyProductInfoTests.cs deleted file mode 100644 index 5f7d2b2..0000000 --- a/src/Tests/AssemblyProductInfoTests.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Text; -using ConfigSettings.Internal; -using ConfigSettings.Utils; -using NUnit.Framework; - -namespace ConfigSettingsTests -{ - [TestFixture] - public class AssemblyProductInfoTests - { - [Test] - public void TestAssemblyProductInfo() - { - var assembly = Assembly.GetExecutingAssembly(); - var companyName = "ConfigSettingsTests"; - var productName = "Test Product Name"; - var normalizedProductName = "TestProductName"; - var assemblyProductInfo = new AssemblyProductInfo(assembly); - Assert.AreEqual(assemblyProductInfo.CompanyName, companyName); - Assert.AreEqual(assemblyProductInfo.ProductName, productName); - Assert.AreEqual(assemblyProductInfo.NormalizedProductName, normalizedProductName); - } - } -} \ No newline at end of file diff --git a/src/Tests/ChangeConfig/ChangeConfigWithEtalonTests.cs b/src/Tests/ChangeConfig/ChangeConfigWithEtalonTests.cs index 90fbc31..2d8de2b 100644 --- a/src/Tests/ChangeConfig/ChangeConfigWithEtalonTests.cs +++ b/src/Tests/ChangeConfig/ChangeConfigWithEtalonTests.cs @@ -2,10 +2,10 @@ using System.IO; using System.Linq; using System.Threading.Tasks; +using ConfigSettings.Utils; using FluentAssertions; using NUnit.Framework; using TestStack.BDDfy; -using ConfigSettings.Internal; namespace ConfigSettings.Tests { @@ -53,20 +53,29 @@ public void FindPathByMaskTest() [Test] public void ApplyLogSettings() { - this.When(_ => _.ApplySettingsToLogСonfig()) + var currentConfigPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ChangeConfig", "Etalon", "source_log.config"); + this.When(_ => _.ApplySettingsToLogСonfig(currentConfigPath)) .Then(_ => _.ConfigShouldContainsFullPath()) - .And(_ => _.ConfigFullPathShouldNotContainsAppdata()) + .And(_ => _.ConfigFullPathShouldNotContainsAppdata(currentConfigPath)) .BDDfy(); } [Test] public void ApplyConfigSettingsAppDataPath() { - this.When(_ => _.ApplySettingsToLogСonfigWithAppDataPath()) - .Then(_ => _.ConfigFullPathShouldContainsAppdata()) + var currentConfigPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ChangeConfig", "Etalon", "source_log.config"); + this.When(_ => _.ApplySettingsToLogСonfigWithAppDataPath(currentConfigPath)) + .Then(_ => _.ConfigFullPathShouldContainsAppdata(currentConfigPath)) .BDDfy(); } + [Test] + public void ApplyConfigSettingsAppDataPathWithoutResolveFunc() + { + var currentConfigPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ChangeConfig", "Etalon", "source_log.config"); + Assert.Throws(() => ApplySettingsToLogСonfigWithAppDataPathWithoutResolvePathFunc(currentConfigPath)); + } + private void ConfigShouldContainsFullPath() { var existingPathPart = Path.GetDirectoryName(Path.GetDirectoryName(Path.GetFullPath(this.liveConfigPath))); @@ -74,14 +83,14 @@ private void ConfigShouldContainsFullPath() File.ReadAllText(this.liveConfigPath).Contains(existingPathPart).Should().BeTrue(); } - private void ConfigFullPathShouldContainsAppdata() + private void ConfigFullPathShouldContainsAppdata(string currentConfigPath) { - this.liveConfigPath.Contains(SpecialFolders.ProductUserApplicationData("Configs")).Should().BeTrue(); + this.liveConfigPath.Contains(ResolveForcedAppDataPath(currentConfigPath)).Should().BeTrue(); } - private void ConfigFullPathShouldNotContainsAppdata() + private void ConfigFullPathShouldNotContainsAppdata(string currentConfigPath) { - this.liveConfigPath.Contains(SpecialFolders.ProductUserApplicationData("Configs")).Should().BeFalse(); + this.liveConfigPath.Contains(ResolveForcedAppDataPath(currentConfigPath)).Should().BeFalse(); } @@ -89,7 +98,7 @@ private void FindPathByMask() { var fn = Guid.NewGuid().ToString(); ChangeConfig.FindFirstPathByMask(this.tempPath, fn).Should().BeNull(); - File.WriteAllText(Path.Combine(this.tempPath, "prefix_"+fn), "some content"); + File.WriteAllText(Path.Combine(this.tempPath, "prefix_" + fn), "some content"); ChangeConfig.FindFirstPathByMask(this.tempPath, fn).Should().EndWith(fn); } @@ -140,14 +149,28 @@ private void LiveConfigShouldBeEqualToEtalon() diff.Should().BeEmpty(); } - private void ApplySettingsToLogСonfig() + private void ApplySettingsToLogСonfig(string currentConfigPath) + { + this.liveConfigPath = ChangeConfig.Execute(currentConfigPath, Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ChangeConfig", "Etalon", "settings.xml"), ResolveForcedAppDataPath); + } + + private void ApplySettingsToLogСonfigWithAppDataPath(string currentConfigPath) + { + this.liveConfigPath = ChangeConfig.Execute(currentConfigPath, Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ChangeConfig", "Etalon", "settings_with_appdata_path.xml"), ResolveForcedAppDataPath); + } + + private void ApplySettingsToLogСonfigWithAppDataPathWithoutResolvePathFunc(string currentConfigPath) { - this.liveConfigPath = ChangeConfig.Execute(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ChangeConfig", "Etalon", "source_log.config"), Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ChangeConfig", "Etalon", "settings.xml")); + this.liveConfigPath = ChangeConfig.Execute(currentConfigPath, Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ChangeConfig", "Etalon", "settings_with_appdata_path.xml")); } - private void ApplySettingsToLogСonfigWithAppDataPath() + private static string ResolveForcedAppDataPath(string currentConfigPath) { - this.liveConfigPath = ChangeConfig.Execute(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ChangeConfig", "Etalon", "source_log.config"), Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ChangeConfig", "Etalon", "settings_with_appdata_path.xml")); + return Path.Combine( + Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), + "ConfigSettings", + "Configs", + Path.GetDirectoryName(currentConfigPath).GetMD5Hash().Substring(0, 8)); } } }