Skip to content

Commit 60f78a4

Browse files
authored
Merge pull request microsoft#1854 from mjcheetham/version-parsing
Improved Git version parsing to support release candidates
2 parents 3e720b9 + e30e98f commit 60f78a4

2 files changed

Lines changed: 110 additions & 45 deletions

File tree

GVFS/GVFS.Common/Git/GitVersion.cs

Lines changed: 62 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
using System;
2-
using System.Text;
32

43
namespace GVFS.Common.Git
54
{
65
public class GitVersion
76
{
87
public GitVersion(int major, int minor, int build, string platform = null, int revision = 0, int minorRevision = 0)
8+
: this(major, minor, build, null, platform, revision, minorRevision) { }
9+
10+
public GitVersion(int major, int minor, int build, int? releaseCandidate = null, string platform = null, int revision = 0, int minorRevision = 0)
911
{
1012
this.Major = major;
1113
this.Minor = minor;
1214
this.Build = build;
15+
this.ReleaseCandidate = releaseCandidate;
1316
this.Platform = platform;
1417
this.Revision = revision;
1518
this.MinorRevision = minorRevision;
@@ -18,6 +21,7 @@ public GitVersion(int major, int minor, int build, string platform = null, int r
1821
public int Major { get; private set; }
1922
public int Minor { get; private set; }
2023
public int Build { get; private set; }
24+
public int? ReleaseCandidate { get; private set; }
2125
public string Platform { get; private set; }
2226
public int Revision { get; private set; }
2327
public int MinorRevision { get; private set; }
@@ -37,31 +41,12 @@ public static bool TryParseGitVersionCommandResult(string input, out GitVersion
3741
return TryParseVersion(input, out version);
3842
}
3943

40-
public static bool TryParseInstallerName(string input, string installerExtension, out GitVersion version)
41-
{
42-
// Installer name is of the form
43-
// Git-2.14.1.gvfs.1.1.gb16030b-64-bit.exe
44-
45-
version = null;
46-
47-
if (!input.StartsWith("Git-", StringComparison.InvariantCultureIgnoreCase))
48-
{
49-
return false;
50-
}
51-
52-
if (!input.EndsWith("-64-bit" + installerExtension, StringComparison.InvariantCultureIgnoreCase))
53-
{
54-
return false;
55-
}
56-
57-
return TryParseVersion(input.Substring(4, input.Length - 15), out version);
58-
}
59-
6044
public static bool TryParseVersion(string input, out GitVersion version)
6145
{
6246
version = null;
6347

6448
int major, minor, build, revision = 0, minorRevision = 0;
49+
int? releaseCandidate = null;
6550
string platform = null;
6651

6752
if (string.IsNullOrWhiteSpace(input))
@@ -73,10 +58,10 @@ public static bool TryParseVersion(string input, out GitVersion version)
7358
int numComponents = parsedComponents.Length;
7459

7560
// We minimally accept the official Git version number format which
76-
// consists of three components: "major.minor.build".
61+
// consists of three components: "major.minor.build[.rcN]".
7762
//
7863
// The other supported formats are the Git for Windows and Microsoft Git
79-
// formats which look like: "major.minor.build.platform.revision.minorRevision"
64+
// formats which look like: "major.minor.build[.rcN].platform.revision.minorRevision"
8065
// 0 1 2 3 4 5
8166
// len 1 2 3 4 5 6
8267
//
@@ -103,25 +88,54 @@ public static bool TryParseVersion(string input, out GitVersion version)
10388
return false;
10489
}
10590

106-
// Take the platform component verbatim
91+
// Release candidate and/or platform
92+
// Both of these are optional, but the release candidate is expected to be of the format 'rcN'
93+
// where N is a number, helping us distinguish it from a platform string.
94+
int platformIdx = 3;
10795
if (numComponents >= 4)
10896
{
109-
platform = parsedComponents[3];
97+
string tag = parsedComponents[3];
98+
99+
// Release candidate 'rcN'
100+
if (tag.StartsWith("rc", StringComparison.OrdinalIgnoreCase) &&
101+
tag.Length > 2 && int.TryParse(tag.Substring(2), out int rc) && rc >= 0)
102+
{
103+
releaseCandidate = rc;
104+
105+
// The next component will now be the (optional) platform.
106+
// Subsequent components will be revision and minor revision so we need to adjust
107+
// the platform index to account for the release candidate.
108+
platformIdx = 4;
109+
if (numComponents >= 5)
110+
{
111+
platform = parsedComponents[4];
112+
}
113+
}
114+
else // Platform string only
115+
{
116+
platform = tag;
117+
}
110118
}
111119

112120
// Platform revision
113-
if (numComponents < 5 || !TryParseComponent(parsedComponents[4], out revision))
121+
if (numComponents > platformIdx + 1)
114122
{
115-
revision = 0;
123+
if (!TryParseComponent(parsedComponents[platformIdx + 1], out revision))
124+
{
125+
revision = 0;
126+
}
116127
}
117128

118129
// Minor platform revision
119-
if (numComponents < 6 || !TryParseComponent(parsedComponents[5], out minorRevision))
130+
if (numComponents > platformIdx + 2)
120131
{
121-
minorRevision = 0;
132+
if (!TryParseComponent(parsedComponents[platformIdx + 2], out minorRevision))
133+
{
134+
minorRevision = 0;
135+
}
122136
}
123137

124-
version = new GitVersion(major, minor, build, platform, revision, minorRevision);
138+
version = new GitVersion(major, minor, build, releaseCandidate, platform, revision, minorRevision);
125139
return true;
126140
}
127141

@@ -142,7 +156,12 @@ public bool IsLessThan(GitVersion other)
142156

143157
public override string ToString()
144158
{
145-
return string.Format("{0}.{1}.{2}.{3}.{4}.{5}", this.Major, this.Minor, this.Build, this.Platform, this.Revision, this.MinorRevision);
159+
if (ReleaseCandidate is null)
160+
{
161+
return $"{Major}.{Minor}.{Build}.{Platform}.{Revision}.{MinorRevision}";
162+
}
163+
164+
return $"{Major}.{Minor}.{Build}.rc{ReleaseCandidate}.{Platform}.{Revision}.{MinorRevision}";
146165
}
147166

148167
private static bool TryParseComponent(string component, out int parsedComponent)
@@ -182,6 +201,18 @@ private int CompareVersionNumbers(GitVersion other)
182201
return this.Build.CompareTo(other.Build);
183202
}
184203

204+
if (this.ReleaseCandidate != other.ReleaseCandidate)
205+
{
206+
if (this.ReleaseCandidate.HasValue && other.ReleaseCandidate.HasValue)
207+
{
208+
return this.ReleaseCandidate.Value.CompareTo(other.ReleaseCandidate.Value);
209+
}
210+
211+
// If one version has a release candidate and the other does not,
212+
// the one without a release candidate is considered "greater than" the one with.
213+
return other.ReleaseCandidate.HasValue ? 1 : -1;
214+
}
215+
185216
if (this.Revision != other.Revision)
186217
{
187218
return this.Revision.CompareTo(other.Revision);

GVFS/GVFS.UnitTests/Common/GitVersionTests.cs

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
using GVFS.Common;
2-
using GVFS.Common.Git;
1+
using GVFS.Common.Git;
32
using GVFS.Tests.Should;
43
using NUnit.Framework;
54

@@ -8,14 +7,6 @@ namespace GVFS.UnitTests.Common
87
[TestFixture]
98
public class GitVersionTests
109
{
11-
[TestCase]
12-
public void TryParseInstallerName()
13-
{
14-
this.ParseAndValidateInstallerVersion("Git-1.2.3.gvfs.4.5.gb16030b-64-bit" + GVFSPlatform.Instance.Constants.InstallerExtension);
15-
this.ParseAndValidateInstallerVersion("git-1.2.3.gvfs.4.5.gb16030b-64-bit" + GVFSPlatform.Instance.Constants.InstallerExtension);
16-
this.ParseAndValidateInstallerVersion("Git-1.2.3.gvfs.4.5.gb16030b-64-bit" + GVFSPlatform.Instance.Constants.InstallerExtension);
17-
}
18-
1910
[TestCase]
2011
public void Version_Data_Null_Returns_False()
2112
{
@@ -118,6 +109,46 @@ public void Compare_Version_Minor_Greater()
118109
version1.IsEqualTo(version2).ShouldEqual(false);
119110
}
120111

112+
[TestCase]
113+
public void Compare_ReleaseCandidate_Less()
114+
{
115+
GitVersion version1 = new GitVersion(1, 2, 3, 1, "test", 4, 1);
116+
GitVersion version2 = new GitVersion(1, 2, 3, 2, "test", 4, 1);
117+
118+
version1.IsLessThan(version2).ShouldEqual(true);
119+
version1.IsEqualTo(version2).ShouldEqual(false);
120+
}
121+
122+
[TestCase]
123+
public void Compare_ReleaseCandidate_Greater()
124+
{
125+
GitVersion version1 = new GitVersion(1, 2, 3, 2, "test", 4, 1);
126+
GitVersion version2 = new GitVersion(1, 2, 3, 1, "test", 4, 1);
127+
128+
version1.IsLessThan(version2).ShouldEqual(false);
129+
version1.IsEqualTo(version2).ShouldEqual(false);
130+
}
131+
132+
[TestCase]
133+
public void Compare_ReleaseCandidate_NonRC_Less()
134+
{
135+
GitVersion version1 = new GitVersion(1, 2, 3, 0, "test", 4, 1);
136+
GitVersion version2 = new GitVersion(1, 2, 3, null, "test", 4, 1);
137+
138+
version1.IsLessThan(version2).ShouldEqual(true);
139+
version1.IsEqualTo(version2).ShouldEqual(false);
140+
}
141+
142+
[TestCase]
143+
public void Compare_ReleaseCandidate_NonRC_Greater()
144+
{
145+
GitVersion version1 = new GitVersion(1, 2, 3, null, "test", 4, 1);
146+
GitVersion version2 = new GitVersion(1, 2, 3, 0, "test", 4, 1);
147+
148+
version1.IsLessThan(version2).ShouldEqual(false);
149+
version1.IsEqualTo(version2).ShouldEqual(false);
150+
}
151+
121152
[TestCase]
122153
public void Compare_Version_Build_Less()
123154
{
@@ -187,6 +218,7 @@ public void Allow_Blank_Minor_Revision()
187218
version.Major.ShouldEqual(1);
188219
version.Minor.ShouldEqual(2);
189220
version.Build.ShouldEqual(3);
221+
version.ReleaseCandidate.ShouldEqual(null);
190222
version.Platform.ShouldEqual("test");
191223
version.Revision.ShouldEqual(4);
192224
version.MinorRevision.ShouldEqual(0);
@@ -201,21 +233,23 @@ public void Allow_Invalid_Minor_Revision()
201233
version.Major.ShouldEqual(1);
202234
version.Minor.ShouldEqual(2);
203235
version.Build.ShouldEqual(3);
236+
version.ReleaseCandidate.ShouldEqual(null);
204237
version.Platform.ShouldEqual("test");
205238
version.Revision.ShouldEqual(4);
206239
version.MinorRevision.ShouldEqual(0);
207240
}
208241

209-
private void ParseAndValidateInstallerVersion(string installerName)
242+
[TestCase]
243+
public void Allow_ReleaseCandidates()
210244
{
211245
GitVersion version;
212-
bool success = GitVersion.TryParseInstallerName(installerName, GVFSPlatform.Instance.Constants.InstallerExtension, out version);
213-
success.ShouldBeTrue();
246+
GitVersion.TryParseVersion("1.2.3.rc2.test.4.5", out version).ShouldEqual(true);
214247

215248
version.Major.ShouldEqual(1);
216249
version.Minor.ShouldEqual(2);
217250
version.Build.ShouldEqual(3);
218-
version.Platform.ShouldEqual("gvfs");
251+
version.ReleaseCandidate.ShouldEqual(2);
252+
version.Platform.ShouldEqual("test");
219253
version.Revision.ShouldEqual(4);
220254
version.MinorRevision.ShouldEqual(5);
221255
}

0 commit comments

Comments
 (0)