Пример #1
0
        public void when_building_config_then_file_can_be_missing()
        {
            var dir    = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
            var config = Config.Build(dir);

            Assert.False(File.Exists(config.FilePath));
        }
        public void can_load()
        {
            var file = Path.GetTempFileName();

            File.WriteAllText(file, @"
[sleet]
    feedLockTimeoutMinutes = 30
    username = kzu
    useremail = [email protected]

[sleet ""AzureFeed""]
    type = azure
    container = feed
    connectionString = ""DefaultEndpointsProtocol=https;AccountName=myaccount;AccountKey=;BlobEndpoint=""
    path = https://myaccount.blob.core.windows.net/feed/
    feedSubPath = subPath

[sleet ""AmazonFeed""]
    type = s3
    bucketName = bucket
    region = us-east-1
    profileName = profile
    path = https://s3.amazonaws.com/my-bucket/
    feedSubPath = subPath
    serverSideEncryptionMethod = AES256
    compress

[sleet ""FolderFeed""]
    type = local
    path = C:\\feed
");

            Config.Build(file);
        }
Пример #3
0
        public void can_read_hierarchical_with_config_entry_level()
        {
            var config = Config.Build(Path.Combine(Directory.GetCurrentDirectory(), "Content", "local"));

            foreach (var entry in config.GetRegex("core"))
            {
                switch (entry.Variable)
                {
                case "local":
                case "parent":
                    Assert.Null(entry.Level);
                    break;

                case "global":
                    Assert.Equal(ConfigLevel.Global, entry.Level);
                    break;

                case "system":
                    Assert.Equal(ConfigLevel.System, entry.Level);
                    break;

                default:
                    break;
                }
            }
        }
Пример #4
0
        public void can_read_hierarchical_from_root_file()
        {
            var config = Config.Build("C:\\.netconfig");

            Assert.True(config.GetBoolean("core", "global"));
            Assert.True(config.GetBoolean("core", "system"));
        }
Пример #5
0
        public void can_read_hierarchical_from_relative_path()
        {
            var config = Config.Build(Config.FileName);

            Assert.True(config.GetBoolean("core", "global"));
            Assert.True(config.GetBoolean("core", "system"));
        }
Пример #6
0
        public void can_write_new_file()
        {
            var file   = Path.GetTempFileName();
            var config = Config.Build(file)
                         .SetBoolean("section", "subsection", "bool", true);

            Assert.True(config.GetBoolean("section", "subsection", "bool"));
        }
Пример #7
0
        public void can_read_global()
        {
            var config = Config.Build(ConfigLevel.Global);

            Assert.Null(config.GetBoolean("core", "local"));
            Assert.Null(config.GetBoolean("core", "parent"));
            Assert.True(config.GetBoolean("core", "global"));
            Assert.True(config.GetBoolean("core", "system"));
        }
Пример #8
0
        public void when_reading_non_existent_file_then_values_are_null()
        {
            var config = Config.Build(Path.GetTempFileName());

            Assert.Null(config.GetBoolean("core", "bool"));
            Assert.Null(config.GetBoolean("core", "bool"));
            Assert.Null(config.GetString("core", "string"));
            Assert.Null(config.GetNumber("core", "int"));
            Assert.Null(config.GetNumber("core", "int"));
        }
Пример #9
0
        public void given_command_tree_sets_all_default()
        {
            var config = Config.Build(Path.GetTempFileName())
                         .SetString("foo", "name", "foo")
                         .SetString("foo", "bar", "name", "bar")
                         .SetBoolean("foo", "baz", "force", true)
                         .SetString("foo", "baz.update", "name", "baz");

            var command = new Command("foo")
            {
                new Command("bar")
                {
                    new Argument <string?>("name"),
                },
                new Command("baz")
                {
                    new Command("update")
                    {
                        new Argument <string?>("name"),
                    },
                    new Command("install")
                    {
                        new Argument <string?>("name"),
                    },
                    new Command("uninstall")
                    {
                        new Argument <string?>("name"),
                        new Option <bool?>("force"),
                    },
                },
            }.WithConfigurableDefaults(configuration: config);

            Assert.True(Traverse
                        .BreadthFirst(command, c => c.Children.OfType <Command>())
                        .SelectMany(x => x.Arguments).All(x => x.HasDefaultValue));

            // Gets from the command-specific section
            Assert.Equal("bar", command.Children.OfType <Command>().First().Arguments.First().GetDefaultValue());
            Assert.Equal("baz", Traverse
                         .DepthFirst(command, c => c.Children.OfType <Command>())
                         .First(c => c.Name == "update")
                         .Arguments.First().GetDefaultValue());

            // Uses default from lifted top-level section for shared "name" argument
            Assert.Equal("foo", Traverse
                         .DepthFirst(command, c => c.Children.OfType <Command>())
                         .First(c => c.Name == "install")
                         .Arguments.First().GetDefaultValue());

            // Non-shared but still lifted since no conflicts
            Assert.True(Traverse
                        .DepthFirst(command, c => c.Children.OfType <Command>())
                        .First(c => c.Name == "uninstall")
                        .Options.OfType <IOption>().First().Argument.GetDefaultValue() as bool?);
        }
Пример #10
0
        public void can_roundtrip()
        {
            var file   = Path.GetTempFileName();
            var config = Config.Build(file);

            config.SetString("section", "subsection", "foo", "bar");

            var value = Config.Build(file).GetString("section", "subsection", "foo");

            Assert.Equal("bar", value);
        }
        public async Task reading_from_multiple_threads_succeeds()
        {
            Config.GlobalLocation      = Path.Combine(Directory.GetCurrentDirectory(), "Content", "global.netconfig");
            Config.SystemLocation      = Path.Combine(Directory.GetCurrentDirectory(), "Content", "system.netconfig");
            CultureInfo.CurrentCulture = CultureInfo.InvariantCulture;

            var path = Path.Combine(Directory.GetCurrentDirectory(), "Content", ".netconfig");

            await Task.WhenAll(Enumerable
                               .Range(0, 5)
                               .Select(_ => Task.Run(() => Config.Build(path)))
                               .ToArray());
        }
        public void can_save_values()
        {
            var config = BuildConfiguration();

            config["foo:enabled"] = "true";
            config["foo:bar:baz"] = "bye";
            config["http:https://weaker.example.com:sslVerify"] = "false";

            var dotnet = Config.Build(Path.Combine(Constants.CurrentDirectory, "Content", "web", nameof(can_save_values)));

            Assert.Equal("true", dotnet.GetString("foo", "enabled"));
            Assert.Equal("bye", dotnet.GetString("foo", "bar", "baz"));
            Assert.Equal("false", dotnet.GetString("http", "https://weaker.example.com", "sslVerify"));
        }
Пример #13
0
        public void when_reading_local_file_as_root_then_parent_variable_is_null()
        {
            var path = Path.Combine(Path.Combine(Directory.GetCurrentDirectory(), "Content", Guid.NewGuid().ToString()));

            Directory.CreateDirectory(path);
            var config = Config.Build(path);

            config.SetBoolean("config", "root", true);

            // Reload after the value was set.
            config = Config.Build(path);

            Assert.Null(config.GetBoolean("config", "parent"));
        }
Пример #14
0
        public void when_reading_local_file_with_system_false_then_system_variable_is_null()
        {
            var path = Path.Combine(Path.Combine(Directory.GetCurrentDirectory(), "Content", Guid.NewGuid().ToString()));

            Directory.CreateDirectory(path);
            var config = Config.Build(path);

            config.SetBoolean("config", "system", false);

            // Reload after the value was set.
            config = Config.Build(path);

            Assert.Null(config.GetBoolean("core", "system"));
        }
Пример #15
0
        public void when_setting_local_variable_then_writes_user_file()
        {
            Config.GlobalLocation = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString(), ".netconfig");
            Config.SystemLocation = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString(), ".netconfig");

            var path   = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString())).FullName;
            var config = Config.Build(path);

            config.AddString("foo", "bar", "baz", ConfigLevel.Local);

            Assert.True(File.Exists(Path.Combine(path, Config.FileName + ".user")));

            using var reader = new ConfigReader(Path.Combine(path, Config.FileName + ".user"));

            Assert.Single(reader.ReadAllLines().Where(x => x.Kind == LineKind.Variable && x.Variable == "bar" && x.Value == "baz"));
        }
Пример #16
0
        public void when_setting_variable_in_global_dir_then_writes_global_file()
        {
            Config.GlobalLocation = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString(), ".netconfig");
            Config.SystemLocation = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString(), ".netconfig");

            // Simulates opening a cli app from the user's profile dir
            Directory.CreateDirectory(Path.GetDirectoryName(Config.GlobalLocation) !);
            Directory.SetCurrentDirectory(Path.GetDirectoryName(Config.GlobalLocation) !);
            var config = Config.Build();

            config.SetString("foo", "bar", "baz");

            var global = Config.Build(ConfigLevel.Global);

            Assert.Equal("baz", global.GetString("foo", "bar"));
        }
Пример #17
0
        public void can_read_hierarchical()
        {
            var config = Config.Build(Path.Combine(Directory.GetCurrentDirectory(), "Content", "local"));

            Assert.True(config.GetBoolean("core", "local"));
            Assert.True(config.GetBoolean("core", "parent"));
            Assert.True(config.GetBoolean("core", "global"));
            Assert.True(config.GetBoolean("core", "system"));

            var section = config.GetSection("core");

            Assert.True(section.GetBoolean("local"));
            Assert.True(section.GetBoolean("parent"));
            Assert.True(section.GetBoolean("global"));
            Assert.True(section.GetBoolean("system"));
        }
Пример #18
0
        public void given_long_array_sets_all_values()
        {
            var config = Config.Build(Path.GetTempFileName())
                         .AddNumber("cli", "include", 25)
                         .AddNumber("cli", "include", 50)
                         .AddNumber("cli", "include", 100);

            var command = new RootCommand()
            {
                new Argument <long[]>("include"),
            }.WithConfigurableDefaults("cli", configuration: config);

            command.Handler = CommandHandler.Create <long[]>(include =>
                                                             Assert.Equal(new long[] { 25, 50, 100 }, include));

            new CommandLineBuilder(command).Build().Invoke(new string[] { });
        }
Пример #19
0
        public void when_setting_local_variable_then_overrides_default_file()
        {
            Config.GlobalLocation = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString(), ".netconfig");
            Config.SystemLocation = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString(), ".netconfig");

            var path = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString())).FullName;

            File.WriteAllText(Path.Combine(path, ".netconfig"), @"[foo]
bar = baz");
            File.WriteAllText(Path.Combine(path, ".netconfig.user"), @"[foo]
bar = hey");


            var config = Config.Build(path);

            Assert.Equal("hey", config.GetString("foo", "bar"));
        }
Пример #20
0
        public void when_setting_system_variable_then_writes_global_file()
        {
            Config.GlobalLocation = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString(), ".netconfig");
            Config.SystemLocation = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString(), ".netconfig");

            var path = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString())).FullName;

            File.WriteAllText(Path.Combine(path, ".netconfig"), "");

            var config = Config.Build(path);

            config.AddBoolean("test", "var", true, ConfigLevel.System);

            var global = Config.Build(ConfigLevel.System);

            Assert.True(global.GetBoolean("test", "var"));
        }
Пример #21
0
        public void when_reading_hierarchical_from_file_reads_system_once()
        {
            Config.SystemLocation = Path.Combine(Directory.GetCurrentDirectory(), "Content", ".netconfig");

            var config = Config.Build(Path.Combine(Directory.GetCurrentDirectory(), "Content", "local", ".netconfig"));

            Assert.True(config.GetBoolean("core", "local"));
            Assert.True(config.GetBoolean("core", "parent"));

            var section = config.GetSection("core");

            Assert.True(section.GetBoolean("local"));
            Assert.True(section.GetBoolean("parent"));
            Assert.True(section.GetBoolean("global"));

            // Reads the system.netconfig only once, even if the file is in a subfolder
            Assert.Single(config.GetAll("core", "parent"));
        }
        public void saves_to_same_level()
        {
            var dir = Path.Combine(Constants.CurrentDirectory, "Content", "web", nameof(saves_to_same_level));

            Directory.CreateDirectory(dir);
            var usr = Path.Combine(dir, Config.FileName + Config.UserExtension);

            Config.Build(usr).SetNumber("local", "value", 999, ConfigLevel.Local);

            var config = BuildConfiguration();

            Assert.Equal("999", config["local:value"]);

            config["local:value"] = "888";

            Assert.Equal("888", config["local:value"]);
            Assert.Contains("888", File.ReadAllText(usr));
        }
Пример #23
0
        public void when_resolving_path_then_resolves_relative_to_config()
        {
            var globalDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
            var systemDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
            var parentDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
            var localDir  = Path.Combine(parentDir, Guid.NewGuid().ToString());

            Config.GlobalLocation = Path.Combine(globalDir, ".netconfig");
            Config.SystemLocation = Path.Combine(systemDir, ".netconfig");

            Directory.CreateDirectory(globalDir);
            Directory.CreateDirectory(systemDir);
            Directory.CreateDirectory(localDir);

            File.WriteAllText(Config.GlobalLocation, @$ "[file]
    global = .\\global\\file.txt
    dir = .\\global
");
            File.WriteAllText(Config.SystemLocation, @$ "[file]
    system = ./system/file.txt
");
            File.WriteAllText(Path.Combine(parentDir, Config.FileName), @$ "[file]
    parent = file.txt
");
            File.WriteAllText(Path.Combine(localDir, Config.FileName), @$ "[file]
    local = ./file.txt
");

            var config = Config.Build(localDir);

            Assert.Equal(Path.Combine(globalDir, "global"), config.GetNormalizedPath("file", "dir"));
            Assert.Equal(Path.Combine(globalDir, "global", "file.txt"), config.GetNormalizedPath("file", "global"));
            Assert.Equal(Path.Combine(systemDir, "system", "file.txt"), config.GetNormalizedPath("file", "system"));
            Assert.Equal(Path.Combine(parentDir, "file.txt"), config.GetNormalizedPath("file", "parent"));
            Assert.Equal(Path.Combine(localDir, "file.txt"), config.GetNormalizedPath("file", "local"));

            var section = config.GetSection("file");

            Assert.Equal(Path.Combine(globalDir, "global"), section.GetNormalizedPath("dir"));
            Assert.Equal(Path.Combine(globalDir, "global", "file.txt"), section.GetNormalizedPath("global"));
            Assert.Equal(Path.Combine(systemDir, "system", "file.txt"), section.GetNormalizedPath("system"));
            Assert.Equal(Path.Combine(parentDir, "file.txt"), section.GetNormalizedPath("parent"));
            Assert.Equal(Path.Combine(localDir, "file.txt"), section.GetNormalizedPath("local"));
        }
Пример #24
0
        public void given_string_array_sets_all_values()
        {
            var config = Config.Build(Path.GetTempFileName())
                         .AddString("cli", "include", "foo")
                         .AddString("cli", "include", "bar")
                         .AddString("cli", "include", "baz");

            var command = new RootCommand()
            {
                new Argument <string[]>("include"),
            }.WithConfigurableDefaults("cli", configuration: config);

            Assert.Equal(new[] { "foo", "bar", "baz" }, (string[]?)command.Arguments.First().GetDefaultValue());

            command.Handler = CommandHandler.Create <string[]>(include =>
                                                               Assert.Equal(new[] { "foo", "bar", "baz" }, include));

            new CommandLineBuilder(command).Build().Invoke(new string[] { });
        }
Пример #25
0
        static int Run(string[] args)
        {
            var help = false;

            var    action       = ConfigAction.None;
            var    useSystem    = false;
            var    useGlobal    = false;
            var    useLocal     = false;
            var    path         = Directory.GetCurrentDirectory();
            var    nameOnly     = false;
            string?defaultValue = default;
            string?type         = default;
            var    debug        = false;

            var options = new OptionSet
            {
                { Environment.NewLine },
                { Environment.NewLine },
                { "Location (uses all locations by default)" },
                { "local", "use .netconfig.user file", _ => useLocal = true },
                { "global", "use global config file", _ => useGlobal = true },
                { "system", "use system config file", _ => useSystem = true },
                { "path:", "use given config file or directory", f => path = f },

                { Environment.NewLine },
                { "Action" },
                { "get", "get value: name [value-regex]", _ => action = ConfigAction.Get },
                { "get-all", "get all values: key [value-regex]", _ => action = ConfigAction.GetAll },
                { "get-regexp", "get values for regexp: name-regex [value-regex]", _ => action = ConfigAction.GetRegexp },
                { "set", "set value: name value [value-regex]", _ => action = ConfigAction.Set },
                { "set-all", "set all matches: name value [value-regex]", _ => action = ConfigAction.SetAll },
                { "replace-all", "replace all matches: name value [value-regex]", _ => action = ConfigAction.SetAll, true },

                //{ "get-urlmatch", "get value specific for the URL: section[.var] URL", _ => action = ConfigAction.Get },
                { "add", "add a new variable: name value", _ => action = ConfigAction.Add },
                { "unset", "remove a variable: name [value-regex]", _ => action = ConfigAction.Unset },
                { "unset-all", "remove all matches: name [value-regex]", _ => action = ConfigAction.UnsetAll },

                { "remove-section", "remove a section: name", _ => action = ConfigAction.RemoveSection },
                { "rename-section", "rename section: old-name new-name", _ => action = ConfigAction.RenameSection },

                { "l|list", "list all", _ => action = ConfigAction.List },
                { "e|edit", "edit the config file in an editor", _ => action = ConfigAction.Edit },

                { Environment.NewLine },
                { "Other" },
                { "default:", "with --get, use default value when missing entry", v => defaultValue = v },
                { "name-only", "show variable names only", _ => nameOnly = true },
                { "type:", "value is given this type, can be 'boolean', 'datetime' or 'number'", t => type = t },
                { "debug", "add some extra logging for troubleshooting purposes", _ => debug = true, true },

                { "?|h|help", "Display this help", h => help = h != null },
            };

            var extraArgs = options.Parse(args);

            if (debug)
            {
                Console.WriteLine($"::debug::args[{args.Length}]:: {string.Join(" ", args.Select(x => x.IndexOf(' ') != -1 ? $"\"{x}\"" : x))}");
                Console.WriteLine($"::debug::extraargs[{extraArgs.Count}]:: {string.Join(" ", extraArgs.Select(x => x.IndexOf(' ') != -1 ? $"\"{x}\"" : x))}");
            }

            if (args.Length == 1 && help)
            {
                return(ShowHelp(options));
            }

            // Can only use one location
            if ((useGlobal && (useSystem || useLocal)) ||
                (useSystem && (useGlobal || useLocal)) ||
                (useLocal && (useGlobal || useSystem)))
            {
                return(ShowError("Can only specify one config location."));
            }

            ConfigLevel?level = null;
            Config      config;

            if (useGlobal)
            {
                config = Config.Build(ConfigLevel.Global);
                level  = ConfigLevel.Global;
            }
            else if (useSystem)
            {
                config = Config.Build(ConfigLevel.System);
                level  = ConfigLevel.System;
            }
            else
            {
                config = Config.Build(path);
                if (useLocal)
                {
                    level = ConfigLevel.Local;
                }
            }

            // Can be a get or a set, depending on whether a value is provided.
            if (action == ConfigAction.None)
            {
                if (extraArgs.Count == 1)
                {
                    action = ConfigAction.Get;
                }
                else if (extraArgs.Count > 1)
                {
                    action = ConfigAction.Set;
                }
                else
                {
                    return(ShowHelp(options));
                }
            }

            // TODO: For any action that isn't a simple get (which may rely on the output being just the
            // value retrieved), render to the output window the warnings about invalid entries

            Action <ConfigEntry> entryWriter;

            if (nameOnly)
            {
                entryWriter = e => Console.WriteLine(e.Key);
            }
            else
            {
                entryWriter = e => Console.WriteLine($"{e.Key}={(e.RawValue == null ? "" : e.RawValue.Contains(' ') ? "\"" + e.RawValue + "\"" : e.RawValue)}");
            }

            if (type == "date")
            {
                type = "datetime";
            }
            if (type == "bool")
            {
                type = "boolean";
            }

            var kind = ValueKind.String;

            if (type != null && !Enum.TryParse(type, true, out kind))
            {
                Console.Error.WriteLine($"Error: invalid type '{type}'. Expected one of: 'boolean', 'bool', 'datetime', 'date' or 'number'.");
                return(-1);
            }

            string?error = default;

            switch (action)
            {
            case ConfigAction.Add:
            {
                TextRules.ParseKey(extraArgs[0], out var section, out var subsection, out var variable);
                if (extraArgs.Count != 2)
                {
                    return(ShowHelp(options));
                }

                if ((kind == ValueKind.Boolean && !string.IsNullOrEmpty(extraArgs[1]) && !TextRules.TryValidateBoolean(extraArgs[1], out error)) ||
                    (kind == ValueKind.Number && !TextRules.TryValidateNumber(extraArgs[1], out error)) ||
                    kind == ValueKind.DateTime && !DateTime.TryParse(extraArgs[1], CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out _))
                {
                    if (error != null)
                    {
                        return(ShowError(error));
                    }

                    return(ShowError($"Unexpected datetime value `{extraArgs[1]}`, expected ISO 8601 (aka round-trip) format."));
                }

                if (level != null)
                {
                    config.AddString(section !, subsection, variable !, extraArgs[1], level.Value);
                }
                else
                {
                    config.AddString(section !, subsection, variable !, extraArgs[1]);
                }

                break;
            }

            case ConfigAction.Get:
            {
                TextRules.ParseKey(extraArgs[0], out var section, out var subsection, out var variable);

                var value = config.GetString(section !, subsection, variable !);
                Console.WriteLine(value ?? defaultValue ?? "");
                break;
            }

            case ConfigAction.GetAll:
            {
                TextRules.ParseKey(extraArgs[0], out var section, out var subsection, out var variable);

                string?valueRegex = default;
                if (extraArgs.Count > 1)
                {
                    valueRegex = extraArgs[1];
                }

                foreach (var entry in config.GetAll(section !, subsection, variable !, valueRegex))
                {
                    entryWriter(entry);
                }
                break;
            }

            case ConfigAction.GetRegexp:
            {
                if (extraArgs.Count == 0 || extraArgs.Count > 2)
                {
                    return(ShowHelp(options));
                }

                var    nameRegex  = extraArgs[0];
                string?valueRegex = default;
                if (extraArgs.Count > 1)
                {
                    valueRegex = extraArgs[1];
                }

                foreach (var entry in config.GetRegex(nameRegex, valueRegex))
                {
                    entryWriter(entry);
                }
                break;
            }

            case ConfigAction.Set:
            {
                TextRules.ParseKey(extraArgs[0], out var section, out var subsection, out var variable);

                var value = string.Join(' ', extraArgs.Skip(1)).Trim();
                // It's a common mistake to do 'config key = value', so just remove it.
                if (value.StartsWith('='))
                {
                    value = new string(value[1..]).Trim();
Пример #26
0
        public void can_read_local_file()
        {
            var config = Config.Build(Path.Combine(Directory.GetCurrentDirectory(), "Content", "local", ".netconfig"));

            Assert.True(config.GetBoolean("core", "local"));
        }
Пример #27
0
        public void when_reading_local_file_system_variable_is_set()
        {
            var config = Config.Build(Path.Combine(Directory.GetCurrentDirectory(), "Content", "local", ".netconfig"));

            Assert.True(config.GetBoolean("core", "system"));
        }
Пример #28
0
        public void when_build_hierarchical_filepath_is_default()
        {
            var config = Config.Build(Path.Combine(Directory.GetCurrentDirectory(), "Content", "local"));

            Assert.Equal(Path.Combine(Directory.GetCurrentDirectory(), "Content", "local", Config.FileName), config.FilePath);
        }