diff --git a/LibGit2Sharp.Tests/CommitFixture.cs b/LibGit2Sharp.Tests/CommitFixture.cs index 6ac64c31f..a4d7eca44 100644 --- a/LibGit2Sharp.Tests/CommitFixture.cs +++ b/LibGit2Sharp.Tests/CommitFixture.cs @@ -5,6 +5,7 @@ using LibGit2Sharp.Core; using LibGit2Sharp.Tests.TestHelpers; using Xunit; +using Xunit.Extensions; namespace LibGit2Sharp.Tests { @@ -519,6 +520,27 @@ public void DirectlyAccessingAnUnknownTreeEntryOfTheCommitReturnsNull() } } + [Theory] + [InlineData(null, "x@example.com")] + [InlineData("", "x@example.com")] + [InlineData("X", null)] + [InlineData("X", "")] + public void CommitWithInvalidSignatureConfigThrows(string name, string email) + { + string repoPath = InitNewRepository(); + string configPath = CreateConfigurationWithDummyUser(name, email); + var options = new RepositoryOptions { GlobalConfigurationLocation = configPath }; + + using (var repo = new Repository(repoPath, options)) + { + Assert.Equal(name, repo.Config.GetValueOrDefault("user.name")); + Assert.Equal(email, repo.Config.GetValueOrDefault("user.email")); + + Assert.Throws( + () => repo.Commit("Initial egotistic commit", new CommitOptions { AllowEmptyCommit = true })); + } + } + [Fact] public void CanCommitWithSignatureFromConfig() { diff --git a/LibGit2Sharp.Tests/SignatureFixture.cs b/LibGit2Sharp.Tests/SignatureFixture.cs index 978141837..e40cabd6c 100644 --- a/LibGit2Sharp.Tests/SignatureFixture.cs +++ b/LibGit2Sharp.Tests/SignatureFixture.cs @@ -35,13 +35,7 @@ public void CreatingASignatureWithBadParamsThrows() Assert.Throws(() => new Signature(null, "me@there.com", DateTimeOffset.Now)); Assert.Throws(() => new Signature(string.Empty, "me@there.com", DateTimeOffset.Now)); Assert.Throws(() => new Signature("Me", null, DateTimeOffset.Now)); - } - - [Fact] - public void CanCreateASignatureWithAnEmptyEmail() - { - var sig = new Signature("Me", string.Empty, DateTimeOffset.Now); - Assert.Equal(string.Empty, sig.Email); + Assert.Throws(() => new Signature("Me", string.Empty, DateTimeOffset.Now)); } } } diff --git a/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs b/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs index 2cab50d5a..dd2ab2c37 100644 --- a/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs +++ b/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs @@ -298,6 +298,11 @@ private static RepositoryOptions BuildFakeRepositoryOptions(SelfCleaningDirector /// The signature to use for user.name and user.email /// The path to the configuration file protected string CreateConfigurationWithDummyUser(Signature signature) + { + return CreateConfigurationWithDummyUser(signature.Name, signature.Email); + } + + protected string CreateConfigurationWithDummyUser(string name, string email) { SelfCleaningDirectory scd = BuildSelfCleaningDirectory(); Directory.CreateDirectory(scd.DirectoryPath); @@ -305,8 +310,15 @@ protected string CreateConfigurationWithDummyUser(Signature signature) using (Configuration config = new Configuration(configFilePath)) { - config.Set("user.name", signature.Name, ConfigurationLevel.Global); - config.Set("user.email", signature.Email, ConfigurationLevel.Global); + if (name != null) + { + config.Set("user.name", name, ConfigurationLevel.Global); + } + + if (email != null) + { + config.Set("user.email", email, ConfigurationLevel.Global); + } } return configFilePath; diff --git a/LibGit2Sharp/Configuration.cs b/LibGit2Sharp/Configuration.cs index 9e0a2633d..89059b63e 100644 --- a/LibGit2Sharp/Configuration.cs +++ b/LibGit2Sharp/Configuration.cs @@ -227,6 +227,7 @@ public virtual ConfigurationEntry Get(string key, ConfigurationLevel level /// The configuration file which should be considered as the target of this operation public virtual void Set(string key, T value, ConfigurationLevel level = ConfigurationLevel.Local) { + Ensure.ArgumentNotNull(value, "value"); Ensure.ArgumentNotNullOrEmptyString(key, "key"); using (ConfigurationSafeHandle h = RetrieveConfigurationHandle(level, true, configHandle)) @@ -341,30 +342,37 @@ public virtual Signature BuildSignature(DateTimeOffset now) internal Signature BuildSignature(DateTimeOffset now, bool shouldThrowIfNotFound) { - var name = Get("user.name"); - var email = Get("user.email"); + const string userNameKey = "user.name"; + var name = this.GetValueOrDefault(userNameKey); + var normalizedName = NormalizeUserSetting(shouldThrowIfNotFound, userNameKey, name, + () => "unknown"); + + const string userEmailKey = "user.email"; + var email = this.GetValueOrDefault(userEmailKey); + var normalizedEmail = NormalizeUserSetting(shouldThrowIfNotFound, userEmailKey, email, + () => string.Format( + CultureInfo.InvariantCulture, "{0}@{1}", Environment.UserName, Environment.UserDomainName)); + + return new Signature(normalizedName, normalizedEmail, now); + } - if (shouldThrowIfNotFound) + private string NormalizeUserSetting(bool shouldThrowIfNotFound, string entryName, string currentValue, Func defaultValue) + { + if (!string.IsNullOrEmpty(currentValue)) { - if (name == null || string.IsNullOrEmpty(name.Value)) - { - throw new LibGit2SharpException( - "Can not find Name setting of the current user in Git configuration."); - } + return currentValue; + } - if (email == null || string.IsNullOrEmpty(email.Value)) - { - throw new LibGit2SharpException( - "Can not find Email setting of the current user in Git configuration."); - } + string message = string.Format("Configuration value '{0}' is missing or invalid.", entryName); + + if (shouldThrowIfNotFound) + { + throw new LibGit2SharpException(message); } - var nameForSignature = name == null || string.IsNullOrEmpty(name.Value) ? "unknown" : name.Value; - var emailForSignature = email == null || string.IsNullOrEmpty(email.Value) - ? string.Format("{0}@{1}", Environment.UserName, Environment.UserDomainName) - : email.Value; + Log.Write(LogLevel.Warning, message); - return new Signature(nameForSignature, emailForSignature, now); + return defaultValue(); } private ConfigurationSafeHandle Snapshot() diff --git a/LibGit2Sharp/Signature.cs b/LibGit2Sharp/Signature.cs index 74be26448..7dbb437d7 100644 --- a/LibGit2Sharp/Signature.cs +++ b/LibGit2Sharp/Signature.cs @@ -36,7 +36,7 @@ internal Signature(IntPtr signaturePtr) public Signature(string name, string email, DateTimeOffset when) { Ensure.ArgumentNotNullOrEmptyString(name, "name"); - Ensure.ArgumentNotNull(email, "email"); + Ensure.ArgumentNotNullOrEmptyString(email, "email"); Ensure.ArgumentDoesNotContainZeroByte(name, "name"); Ensure.ArgumentDoesNotContainZeroByte(email, "email");