diff options
author | nulltoken <emeric.fermas@gmail.com> | 2015-06-06 12:19:38 +0300 |
---|---|---|
committer | nulltoken <emeric.fermas@gmail.com> | 2015-06-06 12:19:38 +0300 |
commit | 01b4c5e8e976befb15845190d4719ba80a81bb78 (patch) | |
tree | 03403a23b8e0ea3efff120af1b77483e82abc85a | |
parent | 7202df7e971c1cbb32a7e26236064cde326a4e5a (diff) | |
parent | ca4d15ee5e5588fa1c82b3c9398a5c26a828660a (diff) |
Merge pull request #1042 from libgit2/ntk/config_frompaths
Should we allow Configuration to parse a local repository config?
-rw-r--r-- | LibGit2Sharp.Tests/ConfigurationFixture.cs | 74 | ||||
-rw-r--r-- | LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs | 10 | ||||
-rw-r--r-- | LibGit2Sharp/Configuration.cs | 143 | ||||
-rw-r--r-- | LibGit2Sharp/Repository.cs | 2 |
4 files changed, 182 insertions, 47 deletions
diff --git a/LibGit2Sharp.Tests/ConfigurationFixture.cs b/LibGit2Sharp.Tests/ConfigurationFixture.cs index 78cb71c0..50b6fdc7 100644 --- a/LibGit2Sharp.Tests/ConfigurationFixture.cs +++ b/LibGit2Sharp.Tests/ConfigurationFixture.cs @@ -1,8 +1,10 @@ using System; +using System.Collections.Generic; using System.IO; using System.Linq; using LibGit2Sharp.Tests.TestHelpers; using Xunit; +using Xunit.Extensions; namespace LibGit2Sharp.Tests { @@ -14,35 +16,6 @@ namespace LibGit2Sharp.Tests AssertValueInConfigFile(configFilePath, regex); } - private static string RetrieveGlobalConfigLocation() - { - string[] variables = { "HOME", "USERPROFILE", }; - - foreach (string variable in variables) - { - string potentialLocation = Environment.GetEnvironmentVariable(variable); - if (string.IsNullOrEmpty(potentialLocation)) - { - continue; - } - - string potentialPath = Path.Combine(potentialLocation, ".gitconfig"); - - if (File.Exists(potentialPath)) - { - return potentialPath; - } - } - - throw new InvalidOperationException("Unable to determine the location of '.gitconfig' file."); - } - - private static void AssertValueInGlobalConfigFile(string regex) - { - string configFilePath = RetrieveGlobalConfigLocation(); - AssertValueInConfigFile(configFilePath, regex); - } - [Fact] public void CanUnsetAnEntryFromTheLocalConfiguration() { @@ -256,7 +229,7 @@ namespace LibGit2Sharp.Tests [Fact] public void SettingLocalConfigurationOutsideAReposThrows() { - using (var config = new Configuration(null, null, null)) + using (var config = Configuration.BuildFrom(null, null, null, null)) { Assert.Throws<LibGit2SharpException>(() => config.Set("unittests.intsetting", 3)); } @@ -395,5 +368,46 @@ namespace LibGit2Sharp.Tests Assert.Null(repo.Config.Get<string>("MCHammer.You-cant-touch-this", ConfigurationLevel.System)); } } + + public static IEnumerable<object[]> ConfigAccessors + { + get + { + return new List<object[]> + { + new[] { new Func<string, string>(p => Path.Combine(p, ".git", "config")) }, + new[] { new Func<string, string>(p => Path.Combine(p, ".git")) }, + new[] { new Func<string, string>(p => p) }, + }; + } + } + + [Theory, PropertyData("ConfigAccessors")] + public void CanAccessConfigurationWithoutARepository(Func<string, string> localConfigurationPathProvider) + { + var path = SandboxStandardTestRepoGitDir(); + + string globalConfigPath = CreateConfigurationWithDummyUser(Constants.Signature); + var options = new RepositoryOptions { GlobalConfigurationLocation = globalConfigPath }; + + using (var repo = new Repository(path, options)) + { + repo.Config.Set("my.key", "local"); + repo.Config.Set("my.key", "mouse", ConfigurationLevel.Global); + } + + using (var config = Configuration.BuildFrom(localConfigurationPathProvider(path), globalConfigPath)) + { + Assert.Equal("local", config.Get<string>("my.key").Value); + Assert.Equal("mouse", config.Get<string>("my.key", ConfigurationLevel.Global).Value); + } + } + + [Fact] + public void PassingANonExistingLocalConfigurationFileToBuildFromthrowss() + { + Assert.Throws<FileNotFoundException>(() => Configuration.BuildFrom( + Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()))); + } } } diff --git a/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs b/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs index 01740476..08d7daf0 100644 --- a/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs +++ b/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs @@ -336,19 +336,19 @@ namespace LibGit2Sharp.Tests.TestHelpers protected string CreateConfigurationWithDummyUser(string name, string email) { SelfCleaningDirectory scd = BuildSelfCleaningDirectory(); - Directory.CreateDirectory(scd.DirectoryPath); - string configFilePath = Path.Combine(scd.DirectoryPath, "global-config"); - using (Configuration config = new Configuration(configFilePath)) + string configFilePath = Touch(scd.DirectoryPath, "fake-config"); + + using (Configuration config = Configuration.BuildFrom(configFilePath)) { if (name != null) { - config.Set("user.name", name, ConfigurationLevel.Global); + config.Set("user.name", name); } if (email != null) { - config.Set("user.email", email, ConfigurationLevel.Global); + config.Set("user.email", email); } } diff --git a/LibGit2Sharp/Configuration.cs b/LibGit2Sharp/Configuration.cs index 47b14fb3..b9924c95 100644 --- a/LibGit2Sharp/Configuration.cs +++ b/LibGit2Sharp/Configuration.cs @@ -15,12 +15,11 @@ namespace LibGit2Sharp public class Configuration : IDisposable, IEnumerable<ConfigurationEntry<string>> { + private readonly FilePath repoConfigPath; private readonly FilePath globalConfigPath; private readonly FilePath xdgConfigPath; private readonly FilePath systemConfigPath; - private readonly Repository repository; - private ConfigurationSafeHandle configHandle; /// <summary> @@ -29,19 +28,22 @@ namespace LibGit2Sharp protected Configuration() { } - internal Configuration(Repository repository, string globalConfigurationFileLocation, + internal Configuration(Repository repository, string repositoryConfigurationFileLocation, string globalConfigurationFileLocation, string xdgConfigurationFileLocation, string systemConfigurationFileLocation) { - this.repository = repository; + if (repositoryConfigurationFileLocation != null) + { + repoConfigPath = NormalizeConfigPath(repositoryConfigurationFileLocation); + } globalConfigPath = globalConfigurationFileLocation ?? Proxy.git_config_find_global(); xdgConfigPath = xdgConfigurationFileLocation ?? Proxy.git_config_find_xdg(); systemConfigPath = systemConfigurationFileLocation ?? Proxy.git_config_find_system(); - Init(); + Init(repository); } - private void Init() + private void Init(Repository repository) { configHandle = Proxy.git_config_new(); @@ -56,6 +58,10 @@ namespace LibGit2Sharp Proxy.git_repository_set_config(repository.Handle, configHandle); } + else if (repoConfigPath != null) + { + Proxy.git_config_add_file_ondisk(configHandle, repoConfigPath, ConfigurationLevel.Local); + } if (globalConfigPath != null) { @@ -73,12 +79,126 @@ namespace LibGit2Sharp } } + private FilePath NormalizeConfigPath(FilePath path) + { + if (File.Exists(path.Native)) + { + return path; + } + + if (!Directory.Exists(path.Native)) + { + throw new FileNotFoundException("Cannot find repository configuration file", path.Native); + } + + var configPath = Path.Combine(path.Native, "config"); + + if (File.Exists(configPath)) + { + return configPath; + } + + var gitConfigPath = Path.Combine(path.Native, ".git", "config"); + + if (File.Exists(gitConfigPath)) + { + return gitConfigPath; + } + + throw new FileNotFoundException("Cannot find repository configuration file", path.Native); + } + + /// <summary> + /// Access configuration values without a repository. + /// <para> + /// Generally you want to access configuration via an instance of <see cref="Repository"/> instead. + /// </para> + /// <para> + /// <paramref name="repositoryConfigurationFileLocation"/> can either contains a path to a file or a directory. In the latter case, + /// this can be the working directory, the .git directory or the directory containing a bare repository. + /// </para> + /// </summary> + /// <param name="repositoryConfigurationFileLocation">Path to an existing Repository configuration file.</param> + /// <returns>An instance of <see cref="Configuration"/>.</returns> + public static Configuration BuildFrom( + string repositoryConfigurationFileLocation) + { + return BuildFrom(repositoryConfigurationFileLocation, null, null, null); + } + + /// <summary> + /// Access configuration values without a repository. + /// <para> + /// Generally you want to access configuration via an instance of <see cref="Repository"/> instead. + /// </para> + /// <para> + /// <paramref name="repositoryConfigurationFileLocation"/> can either contains a path to a file or a directory. In the latter case, + /// this can be the working directory, the .git directory or the directory containing a bare repository. + /// </para> + /// </summary> + /// <param name="repositoryConfigurationFileLocation">Path to an existing Repository configuration file.</param> + /// <param name="globalConfigurationFileLocation">Path to a Global configuration file. If null, the default path for a Global configuration file will be probed.</param> + /// <returns>An instance of <see cref="Configuration"/>.</returns> + public static Configuration BuildFrom( + string repositoryConfigurationFileLocation, + string globalConfigurationFileLocation) + { + return BuildFrom(repositoryConfigurationFileLocation, globalConfigurationFileLocation, null, null); + } + + /// <summary> + /// Access configuration values without a repository. + /// <para> + /// Generally you want to access configuration via an instance of <see cref="Repository"/> instead. + /// </para> + /// <para> + /// <paramref name="repositoryConfigurationFileLocation"/> can either contains a path to a file or a directory. In the latter case, + /// this can be the working directory, the .git directory or the directory containing a bare repository. + /// </para> + /// </summary> + /// <param name="repositoryConfigurationFileLocation">Path to an existing Repository configuration file.</param> + /// <param name="globalConfigurationFileLocation">Path to a Global configuration file. If null, the default path for a Global configuration file will be probed.</param> + /// <param name="xdgConfigurationFileLocation">Path to a XDG configuration file. If null, the default path for a XDG configuration file will be probed.</param> + /// <returns>An instance of <see cref="Configuration"/>.</returns> + public static Configuration BuildFrom( + string repositoryConfigurationFileLocation, + string globalConfigurationFileLocation, + string xdgConfigurationFileLocation) + { + return BuildFrom(repositoryConfigurationFileLocation, globalConfigurationFileLocation, xdgConfigurationFileLocation, null); + } + + /// <summary> + /// Access configuration values without a repository. + /// <para> + /// Generally you want to access configuration via an instance of <see cref="Repository"/> instead. + /// </para> + /// <para> + /// <paramref name="repositoryConfigurationFileLocation"/> can either contains a path to a file or a directory. In the latter case, + /// this can be the working directory, the .git directory or the directory containing a bare repository. + /// </para> + /// </summary> + /// <param name="repositoryConfigurationFileLocation">Path to an existing Repository configuration file.</param> + /// <param name="globalConfigurationFileLocation">Path to a Global configuration file. If null, the default path for a Global configuration file will be probed.</param> + /// <param name="xdgConfigurationFileLocation">Path to a XDG configuration file. If null, the default path for a XDG configuration file will be probed.</param> + /// <param name="systemConfigurationFileLocation">Path to a System configuration file. If null, the default path for a System configuration file will be probed.</param> + /// <returns>An instance of <see cref="Configuration"/>.</returns> + public static Configuration BuildFrom( + string repositoryConfigurationFileLocation, + string globalConfigurationFileLocation, + string xdgConfigurationFileLocation, + string systemConfigurationFileLocation) + { + return new Configuration(null, repositoryConfigurationFileLocation, globalConfigurationFileLocation, xdgConfigurationFileLocation, systemConfigurationFileLocation); + } + /// <summary> /// Access configuration values without a repository. Generally you want to access configuration via an instance of <see cref="Repository"/> instead. /// </summary> /// <param name="globalConfigurationFileLocation">Path to a Global configuration file. If null, the default path for a global configuration file will be probed.</param> + [Obsolete("This method will be removed in the next release. Please use Configuration.BuildFrom(string, string) instead.")] public Configuration(string globalConfigurationFileLocation) - : this(null, globalConfigurationFileLocation, null, null) + : this(null, null, globalConfigurationFileLocation, null, null) { } /// <summary> @@ -86,8 +206,9 @@ namespace LibGit2Sharp /// </summary> /// <param name="globalConfigurationFileLocation">Path to a Global configuration file. If null, the default path for a global configuration file will be probed.</param> /// <param name="xdgConfigurationFileLocation">Path to a XDG configuration file. If null, the default path for a XDG configuration file will be probed.</param> + [Obsolete("This method will be removed in the next release. Please use Configuration.BuildFrom(string, string, string) instead.")] public Configuration(string globalConfigurationFileLocation, string xdgConfigurationFileLocation) - : this(null, globalConfigurationFileLocation, xdgConfigurationFileLocation, null) + : this(null, null, globalConfigurationFileLocation, xdgConfigurationFileLocation, null) { } /// <summary> @@ -96,10 +217,10 @@ namespace LibGit2Sharp /// <param name="globalConfigurationFileLocation">Path to a Global configuration file. If null, the default path for a global configuration file will be probed.</param> /// <param name="xdgConfigurationFileLocation">Path to a XDG configuration file. If null, the default path for a XDG configuration file will be probed.</param> /// <param name="systemConfigurationFileLocation">Path to a System configuration file. If null, the default path for a system configuration file will be probed.</param> + [Obsolete("This method will be removed in the next release. Please use Configuration.BuildFrom(string, string, string, string) instead.")] public Configuration(string globalConfigurationFileLocation, string xdgConfigurationFileLocation, string systemConfigurationFileLocation) - : this(null, globalConfigurationFileLocation, xdgConfigurationFileLocation, systemConfigurationFileLocation) - { - } + : this(null, null, globalConfigurationFileLocation, xdgConfigurationFileLocation, systemConfigurationFileLocation) + { } /// <summary> /// Determines which configuration file has been found. diff --git a/LibGit2Sharp/Repository.cs b/LibGit2Sharp/Repository.cs index 79c9077b..51120408 100644 --- a/LibGit2Sharp/Repository.cs +++ b/LibGit2Sharp/Repository.cs @@ -125,7 +125,7 @@ namespace LibGit2Sharp config = new Lazy<Configuration>( () => - RegisterForCleanup(new Configuration(this, configurationGlobalFilePath, configurationXDGFilePath, + RegisterForCleanup(new Configuration(this, null, configurationGlobalFilePath, configurationXDGFilePath, configurationSystemFilePath))); odb = new Lazy<ObjectDatabase>(() => new ObjectDatabase(this)); diff = new Diff(this); |