-
Notifications
You must be signed in to change notification settings - Fork 639
/
MergeMessage.cs
113 lines (91 loc) · 4.45 KB
/
MergeMessage.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
using System.Diagnostics.CodeAnalysis;
using System.Text.RegularExpressions;
using GitVersion.Configuration;
using GitVersion.Extensions;
using GitVersion.Git;
namespace GitVersion;
public class MergeMessage
{
private static readonly IList<MergeMessageFormat> DefaultFormats =
[
new("Default", @"^Merge (branch|tag) '(?<SourceBranch>[^']*)'(?: into (?<TargetBranch>[^\s]*))*"),
new("SmartGit", @"^Finish (?<SourceBranch>[^\s]*)(?: into (?<TargetBranch>[^\s]*))*"),
new("BitBucketPull", @"^Merge pull request #(?<PullRequestNumber>\d+) (from|in) (?<Source>.*) from (?<SourceBranch>[^\s]*) to (?<TargetBranch>[^\s]*)"),
new("BitBucketPullv7", @"^Pull request #(?<PullRequestNumber>\d+).*\r?\n\r?\nMerge in (?<Source>.*) from (?<SourceBranch>[^\s]*) to (?<TargetBranch>[^\s]*)"),
new("BitBucketCloudPull", @"^Merged in (?<SourceBranch>[^\s]*) \(pull request #(?<PullRequestNumber>\d+)\)"),
new("GitHubPull", @"^Merge pull request #(?<PullRequestNumber>\d+) (from|in) (?:[^\s\/]+\/)?(?<SourceBranch>[^\s]*)(?: into (?<TargetBranch>[^\s]*))*"),
new("RemoteTracking", @"^Merge remote-tracking branch '(?<SourceBranch>[^\s]*)'(?: into (?<TargetBranch>[^\s]*))*"),
new("AzureDevOpsPull", @"^Merge pull request (?<PullRequestNumber>\d+) from (?<SourceBranch>[^\s]*) into (?<TargetBranch>[^\s]*)")
];
public MergeMessage(string mergeMessage, IGitVersionConfiguration configuration)
{
mergeMessage.NotNull();
if (mergeMessage == string.Empty) return;
// Concatenate configuration formats with the defaults.
// Ensure configurations are processed first.
var allFormats = configuration.MergeMessageFormats
.Select(x => new MergeMessageFormat(x.Key, x.Value))
.Concat(DefaultFormats);
foreach (var format in allFormats)
{
var match = format.Pattern.Match(mergeMessage);
if (!match.Success)
continue;
FormatName = format.Name;
var sourceBranch = match.Groups["SourceBranch"].Value;
MergedBranch = GetMergedBranchName(sourceBranch);
if (match.Groups["TargetBranch"].Success)
{
TargetBranch = match.Groups["TargetBranch"].Value;
}
if (int.TryParse(match.Groups["PullRequestNumber"].Value, out var pullNumber))
{
PullRequestNumber = pullNumber;
}
Version = ParseVersion(
configuration.VersionInBranchRegex, configuration.TagPrefix, configuration.SemanticVersionFormat
);
break;
}
}
public string? FormatName { get; }
public string? TargetBranch { get; }
public ReferenceName? MergedBranch { get; }
public bool IsMergedPullRequest => PullRequestNumber != null;
public int? PullRequestNumber { get; }
public SemanticVersion? Version { get; }
private SemanticVersion? ParseVersion(Regex versionInBranchRegex, string? tagPrefix, SemanticVersionFormat format)
{
if (MergedBranch?.TryGetSemanticVersion(out var result, versionInBranchRegex, tagPrefix, format) == true)
return result.Value;
return null;
}
private class MergeMessageFormat(string name, string pattern)
{
public string Name { get; } = name;
public Regex Pattern { get; } = new(pattern, RegexOptions.IgnoreCase | RegexOptions.Compiled);
}
private ReferenceName GetMergedBranchName(string mergedBranch)
{
if (FormatName == "RemoteTracking" && !mergedBranch.StartsWith(ReferenceName.RemoteTrackingBranchPrefix))
{
mergedBranch = $"{ReferenceName.RemoteTrackingBranchPrefix}{mergedBranch}";
}
return ReferenceName.FromBranchName(mergedBranch);
}
public static bool TryParse(
ICommit mergeCommit, IGitVersionConfiguration configuration, [NotNullWhen(true)] out MergeMessage? mergeMessage)
{
mergeCommit.NotNull();
configuration.NotNull();
mergeMessage = null;
var mergedBranch = new MergeMessage(mergeCommit.Message, configuration).MergedBranch;
var isReleaseBranch = mergedBranch is not null && configuration.IsReleaseBranch(mergedBranch);
var isValidMergeCommit = mergeCommit.IsMergeCommit() || isReleaseBranch;
if (isValidMergeCommit)
{
mergeMessage = new(mergeCommit.Message, configuration);
}
return isValidMergeCommit;
}
}