From 7452301ceddf991740a58bcabc1b79a0dc209eb6 Mon Sep 17 00:00:00 2001 From: Edwin Engelen Date: Wed, 12 Oct 2016 00:48:19 +0200 Subject: [PATCH] Export custom TFS check-in notes to commit message (#1004) --- GitTfs.VsCommon/TfsHelper.Common.cs | 18 ++------ GitTfs/Core/GitTfsRemote.cs | 26 +++++------ GitTfs/Core/ITfsCheckinNote.cs | 8 ++++ GitTfs/Core/TfsChangesetInfo.cs | 5 +-- GitTfs/Core/TfsCheckinNote.cs | 8 ++++ GitTfs/GitTfs.csproj | 3 ++ GitTfs/GitTfsConstants.cs | 7 --- .../CamelCaseToDelimitedStringConverter.cs | 43 +++++++++++++++++++ GitTfsTest/GitTfsTest.csproj | 1 + ...amelCaseToDelimitedStringConverterTests.cs | 28 ++++++++++++ doc/release-notes/NEXT.md | 1 + 11 files changed, 108 insertions(+), 40 deletions(-) create mode 100644 GitTfs/Core/ITfsCheckinNote.cs create mode 100644 GitTfs/Core/TfsCheckinNote.cs create mode 100644 GitTfs/Util/CamelCaseToDelimitedStringConverter.cs create mode 100644 GitTfsTest/Util/CamelCaseToDelimitedStringConverterTests.cs diff --git a/GitTfs.VsCommon/TfsHelper.Common.cs b/GitTfs.VsCommon/TfsHelper.Common.cs index 48ce4fbf..3e1ea3e0 100644 --- a/GitTfs.VsCommon/TfsHelper.Common.cs +++ b/GitTfs.VsCommon/TfsHelper.Common.cs @@ -568,21 +568,11 @@ namespace Sep.Git.Tfs.VsCommon Url = Linking.GetArtifactUrl(wi.Uri.AbsoluteUri) }); } - foreach (var checkinNote in changeset.CheckinNote.Values) - { - switch (checkinNote.Name) + tfsChangeset.Summary.CheckinNotes = changeset.CheckinNote.Values.Select(note => new TfsCheckinNote { - case GitTfsConstants.CodeReviewer: - tfsChangeset.Summary.CodeReviewer = checkinNote.Value; - break; - case GitTfsConstants.SecurityReviewer: - tfsChangeset.Summary.SecurityReviewer = checkinNote.Value; - break; - case GitTfsConstants.PerformanceReviewer: - tfsChangeset.Summary.PerformanceReviewer = checkinNote.Value; - break; - } - } + Name = note.Name, + Value = note.Value + }); tfsChangeset.Summary.PolicyOverrideComment = changeset.PolicyOverride.Comment; return tfsChangeset; diff --git a/GitTfs/Core/GitTfsRemote.cs b/GitTfs/Core/GitTfsRemote.cs index 0caaa521..ee376a86 100644 --- a/GitTfs/Core/GitTfsRemote.cs +++ b/GitTfs/Core/GitTfsRemote.cs @@ -472,14 +472,11 @@ namespace Sep.Git.Tfs.Core if (!string.IsNullOrWhiteSpace(changeset.Summary.PolicyOverrideComment)) log.Log += "\n" + GitTfsConstants.GitTfsPolicyOverrideCommentPrefix + changeset.Summary.PolicyOverrideComment; - if (!string.IsNullOrWhiteSpace(changeset.Summary.CodeReviewer)) - log.Log += "\n" + GitTfsConstants.GitTfsCodeReviewerPrefix + changeset.Summary.CodeReviewer; - - if (!string.IsNullOrWhiteSpace(changeset.Summary.SecurityReviewer)) - log.Log += "\n" + GitTfsConstants.GitTfsSecurityReviewerPrefix + changeset.Summary.SecurityReviewer; - - if (!string.IsNullOrWhiteSpace(changeset.Summary.PerformanceReviewer)) - log.Log += "\n" + GitTfsConstants.GitTfsPerformanceReviewerPrefix + changeset.Summary.PerformanceReviewer; + foreach (var checkinNote in changeset.Summary.CheckinNotes) + { + if (!string.IsNullOrWhiteSpace(checkinNote.Name) && !string.IsNullOrWhiteSpace(checkinNote.Value)) + log.Log += "\n" + GitTfsConstants.GitTfsPrefix + "-" + CamelCaseToDelimitedStringConverter.Convert(checkinNote.Name, "-") + ":" + checkinNote.Value; + } } var commitSha = Commit(log); @@ -509,14 +506,11 @@ namespace Sep.Git.Tfs.Core if (!string.IsNullOrWhiteSpace(changeset.Summary.PolicyOverrideComment)) metadatas.Append("\nPolicy Override Comment:" + changeset.Summary.PolicyOverrideComment); - if (!string.IsNullOrWhiteSpace(changeset.Summary.CodeReviewer)) - metadatas.Append("\nCode Reviewer:" + changeset.Summary.CodeReviewer); - - if (!string.IsNullOrWhiteSpace(changeset.Summary.SecurityReviewer)) - metadatas.Append("\nSecurity Reviewer:" + changeset.Summary.SecurityReviewer); - - if (!string.IsNullOrWhiteSpace(changeset.Summary.PerformanceReviewer)) - metadatas.Append("\nPerformance Reviewer:" + changeset.Summary.PerformanceReviewer); + foreach (var checkinNote in changeset.Summary.CheckinNotes) + { + if (!string.IsNullOrWhiteSpace(checkinNote.Name) && !string.IsNullOrWhiteSpace(checkinNote.Value)) + metadatas.Append("\n" + checkinNote.Name + ":" + checkinNote.Value); + } if (!string.IsNullOrWhiteSpace(changeset.OmittedParentBranch)) metadatas.Append("\nOmitted parent branch: " + changeset.OmittedParentBranch); diff --git a/GitTfs/Core/ITfsCheckinNote.cs b/GitTfs/Core/ITfsCheckinNote.cs new file mode 100644 index 00000000..bd8aae0c --- /dev/null +++ b/GitTfs/Core/ITfsCheckinNote.cs @@ -0,0 +1,8 @@ +namespace Sep.Git.Tfs.Core +{ + public interface ITfsCheckinNote + { + string Name { get; set; } + string Value { get; set; } + } +} \ No newline at end of file diff --git a/GitTfs/Core/TfsChangesetInfo.cs b/GitTfs/Core/TfsChangesetInfo.cs index 44519a45..00587409 100644 --- a/GitTfs/Core/TfsChangesetInfo.cs +++ b/GitTfs/Core/TfsChangesetInfo.cs @@ -10,15 +10,14 @@ namespace Sep.Git.Tfs.Core public string GitCommit { get; set; } public IEnumerable Workitems { get; set; } - public string CodeReviewer { get; set; } - public string SecurityReviewer { get; set; } - public string PerformanceReviewer { get; set; } + public IEnumerable CheckinNotes { get; set; } public string PolicyOverrideComment { get; set; } public TfsChangesetInfo() { Workitems = Enumerable.Empty(); + CheckinNotes = Enumerable.Empty(); } } } diff --git a/GitTfs/Core/TfsCheckinNote.cs b/GitTfs/Core/TfsCheckinNote.cs new file mode 100644 index 00000000..48bece44 --- /dev/null +++ b/GitTfs/Core/TfsCheckinNote.cs @@ -0,0 +1,8 @@ +namespace Sep.Git.Tfs.Core +{ + public class TfsCheckinNote : ITfsCheckinNote + { + public string Name { get; set; } + public string Value { get; set; } + } +} \ No newline at end of file diff --git a/GitTfs/GitTfs.csproj b/GitTfs/GitTfs.csproj index 88b04a09..b039da18 100644 --- a/GitTfs/GitTfs.csproj +++ b/GitTfs/GitTfs.csproj @@ -109,6 +109,7 @@ + @@ -188,6 +189,7 @@ + @@ -197,6 +199,7 @@ + diff --git a/GitTfs/GitTfsConstants.cs b/GitTfs/GitTfsConstants.cs index 7c264193..0358066c 100644 --- a/GitTfs/GitTfsConstants.cs +++ b/GitTfs/GitTfsConstants.cs @@ -14,9 +14,6 @@ namespace Sep.Git.Tfs public const string TfsRoot = "$/"; public const string GitTfsPrefix = "git-tfs"; public const string GitTfsWorkItemPrefix = GitTfsPrefix + "-work-item:"; - public const string GitTfsCodeReviewerPrefix = GitTfsPrefix + "-code-reviewer:"; - public const string GitTfsSecurityReviewerPrefix = GitTfsPrefix + "-security-reviewer:"; - public const string GitTfsPerformanceReviewerPrefix = GitTfsPrefix + "-performance-reviewer:"; public const string GitTfsPolicyOverrideCommentPrefix = GitTfsPrefix + "-force:"; // e.g. git-tfs-id: [http://team:8080/]$/sandbox;C123 public const string TfsCommitInfoFormat = "git-tfs-id: [{0}]{1};C{2}"; @@ -55,10 +52,6 @@ namespace Sep.Git.Tfs /// public const string RemoteSubtreeFormat = "{0}_subtree/{1}"; - public const string CodeReviewer = "Code Reviewer"; - public const string SecurityReviewer = "Security Reviewer"; - public const string PerformanceReviewer = "Performance Reviewer"; - public const string ExportMetadatasConfigKey = GitTfsPrefix + ".export-metadatas"; public const string WorkspaceConfigKey = GitTfsPrefix + ".workspace-dir"; diff --git a/GitTfs/Util/CamelCaseToDelimitedStringConverter.cs b/GitTfs/Util/CamelCaseToDelimitedStringConverter.cs new file mode 100644 index 00000000..7f6664c3 --- /dev/null +++ b/GitTfs/Util/CamelCaseToDelimitedStringConverter.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Sep.Git.Tfs.Util +{ + public static class CamelCaseToDelimitedStringConverter + { + public static string Convert(string stringWithCamelCase, string delimiter) + { + var words = stringWithCamelCase + .Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries) + .SelectMany(GetCaseDelimitedParts).Select(p => p.ToLowerInvariant()); + + return string.Join(delimiter, words); + } + + private static IEnumerable GetCaseDelimitedParts(string s) + { + var wordStartIndex = 0; + for (var index = 0; index < s.Length; index++) + { + if (IsFirstCharacterOfNewWord(s, index, wordStartIndex)) + { + yield return s.Substring(wordStartIndex, index - wordStartIndex).ToLowerInvariant(); + wordStartIndex = index; + } + } + + yield return s.Substring(wordStartIndex).ToLowerInvariant(); + } + + private static bool IsFirstCharacterOfNewWord(string s, int index, int wordStartIndex) + { + if (index == 0) + return false; + + return char.IsUpper(s[index]) && !char.IsUpper(s[index - 1]) || + char.IsUpper(s[index]) && char.IsUpper(s[index - 1]) && wordStartIndex == index - 2 || + char.IsUpper(s[index]) && char.IsUpper(s[index - 1]) && s.Length >= index + 2 && !char.IsUpper(s[index + 1]); + } + } +} \ No newline at end of file diff --git a/GitTfsTest/GitTfsTest.csproj b/GitTfsTest/GitTfsTest.csproj index 19851a15..2ee0d50b 100644 --- a/GitTfsTest/GitTfsTest.csproj +++ b/GitTfsTest/GitTfsTest.csproj @@ -119,6 +119,7 @@ + diff --git a/GitTfsTest/Util/CamelCaseToDelimitedStringConverterTests.cs b/GitTfsTest/Util/CamelCaseToDelimitedStringConverterTests.cs new file mode 100644 index 00000000..60997abc --- /dev/null +++ b/GitTfsTest/Util/CamelCaseToDelimitedStringConverterTests.cs @@ -0,0 +1,28 @@ +namespace Sep.Git.Tfs.Test.Util +{ + using Sep.Git.Tfs.Util; + using Xunit; + using Xunit.Extensions; + + public class CamelCaseToDelimitedStringConverterTests + { + [Theory] + [InlineData("Code Reviewer", "-", "code-reviewer")] + [InlineData(" Code Reviewer", "-", "code-reviewer")] + [InlineData("Code Reviewer ", "-", "code-reviewer")] + [InlineData(" Code Reviewer ", "-", "code-reviewer")] + [InlineData("Code Reviewer", "-", "code-reviewer")] + [InlineData("CodeReviewer", "-", "code-reviewer")] + [InlineData("Jira Issue ID", "-", "jira-issue-id")] + [InlineData("Jira Issue Id", "-", "jira-issue-id")] + [InlineData("Some IPAddress", "-", "some-ip-address")] + [InlineData("SomeIPAddress", "-", "some-ip-address")] + [InlineData("JustAName", "-", "just-a-name")] + [InlineData("AnOtherDelimiter", "#", "an#other#delimiter")] + public void ReturnsExpectedValue(string stringWithCamelCase, string delimiter, string expected) + { + var actual = CamelCaseToDelimitedStringConverter.Convert(stringWithCamelCase, delimiter); + Assert.Equal(expected, actual); + } + } +} diff --git a/doc/release-notes/NEXT.md b/doc/release-notes/NEXT.md index e69de29b..6523cf63 100644 --- a/doc/release-notes/NEXT.md +++ b/doc/release-notes/NEXT.md @@ -0,0 +1 @@ +* Custom TFS check-in notes are not exported to commit message (#1004, @EdwinEngelen)