Skip to content

Commit 771bb84

Browse files
authored
Merge pull request #154 from AArnott/fix145
Add option for version.json to derive from parents folders
2 parents 72a18cd + 9cff862 commit 771bb84

14 files changed

+1001
-334
lines changed

src/NerdBank.GitVersioning.Tests/BuildIntegrationTests.cs

+9-9
Original file line numberDiff line numberDiff line change
@@ -926,7 +926,7 @@ private void AssertStandardProperties(VersionOptions versionOptions, BuildResult
926926
Assert.Equal(expectedBuildMetadata, buildResult.SemVerBuildSuffix);
927927

928928
// NuGet is now SemVer 2.0 and will pass additional build metadata if provided
929-
bool semVer2 = (versionOptions?.NuGetPackageVersion ?? VersionOptions.NuGetPackageVersionOptions.DefaultInstance).SemVer == 2;
929+
bool semVer2 = versionOptions?.NuGetPackageVersionOrDefault.SemVer == 2;
930930
string pkgVersionSuffix = buildResult.PublicRelease ? string.Empty : $"-g{commitIdShort}";
931931
if (semVer2)
932932
{
@@ -935,19 +935,19 @@ private void AssertStandardProperties(VersionOptions versionOptions, BuildResult
935935

936936
Assert.Equal($"{idAsVersion.Major}.{idAsVersion.Minor}.{idAsVersion.Build}{GetSemVerAppropriatePrereleaseTag(versionOptions)}{pkgVersionSuffix}", buildResult.NuGetPackageVersion);
937937

938-
var buildNumberOptions = versionOptions.CloudBuild?.BuildNumber ?? new VersionOptions.CloudBuildNumberOptions();
939-
if (buildNumberOptions.Enabled)
938+
var buildNumberOptions = versionOptions.CloudBuildOrDefault.BuildNumberOrDefault;
939+
if (buildNumberOptions.EnabledOrDefault)
940940
{
941-
var commitIdOptions = buildNumberOptions.IncludeCommitId ?? new VersionOptions.CloudBuildNumberCommitIdOptions();
941+
var commitIdOptions = buildNumberOptions.IncludeCommitIdOrDefault;
942942
var buildNumberSemVer = SemanticVersion.Parse(buildResult.CloudBuildNumber);
943-
bool hasCommitData = commitIdOptions.When == VersionOptions.CloudBuildNumberCommitWhen.Always
944-
|| (commitIdOptions.When == VersionOptions.CloudBuildNumberCommitWhen.NonPublicReleaseOnly && !buildResult.PublicRelease);
945-
Version expectedVersion = hasCommitData && commitIdOptions.Where == VersionOptions.CloudBuildNumberCommitWhere.FourthVersionComponent
943+
bool hasCommitData = commitIdOptions.WhenOrDefault == VersionOptions.CloudBuildNumberCommitWhen.Always
944+
|| (commitIdOptions.WhenOrDefault == VersionOptions.CloudBuildNumberCommitWhen.NonPublicReleaseOnly && !buildResult.PublicRelease);
945+
Version expectedVersion = hasCommitData && commitIdOptions.WhereOrDefault == VersionOptions.CloudBuildNumberCommitWhere.FourthVersionComponent
946946
? idAsVersion
947947
: new Version(version.Major, version.Minor, version.Build);
948948
Assert.Equal(expectedVersion, buildNumberSemVer.Version);
949949
Assert.Equal(buildResult.PrereleaseVersion, buildNumberSemVer.Prerelease);
950-
string expectedBuildNumberMetadata = hasCommitData && commitIdOptions.Where == VersionOptions.CloudBuildNumberCommitWhere.BuildMetadata
950+
string expectedBuildNumberMetadata = hasCommitData && commitIdOptions.WhereOrDefault == VersionOptions.CloudBuildNumberCommitWhere.BuildMetadata
951951
? $"+g{commitIdShort}"
952952
: string.Empty;
953953
if (additionalBuildMetadata.Any())
@@ -967,7 +967,7 @@ private void AssertStandardProperties(VersionOptions versionOptions, BuildResult
967967

968968
private static string GetSemVerAppropriatePrereleaseTag(VersionOptions versionOptions)
969969
{
970-
return (versionOptions.NuGetPackageVersion ?? VersionOptions.NuGetPackageVersionOptions.DefaultInstance).SemVer == 1
970+
return versionOptions.NuGetPackageVersionOrDefault.SemVer == 1
971971
? versionOptions.Version.Prerelease?.Replace('.', '-')
972972
: versionOptions.Version.Prerelease;
973973
}

src/NerdBank.GitVersioning.Tests/RepoTestBase.cs

+27-13
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,14 @@
1313

1414
public abstract class RepoTestBase : IDisposable
1515
{
16+
private readonly List<string> repoDirectories = new List<string>();
17+
1618
public RepoTestBase(ITestOutputHelper logger)
1719
{
1820
Requires.NotNull(logger, nameof(logger));
1921

2022
this.Logger = logger;
21-
do
22-
{
23-
this.RepoPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
24-
} while (Directory.Exists(this.RepoPath));
25-
Directory.CreateDirectory(this.RepoPath);
23+
this.RepoPath = this.CreateDirectoryForNewRepo();
2624
}
2725

2826
protected ITestOutputHelper Logger { get; }
@@ -39,18 +37,34 @@ public void Dispose()
3937
GC.SuppressFinalize(this);
4038
}
4139

40+
protected string CreateDirectoryForNewRepo()
41+
{
42+
string repoPath;
43+
do
44+
{
45+
repoPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
46+
} while (Directory.Exists(repoPath));
47+
Directory.CreateDirectory(repoPath);
48+
49+
this.repoDirectories.Add(repoPath);
50+
return repoPath;
51+
}
52+
4253
protected virtual void Dispose(bool disposing)
4354
{
4455
if (disposing)
4556
{
4657
this.Repo?.Dispose();
47-
try
48-
{
49-
TestUtilities.DeleteDirectory(this.RepoPath);
50-
}
51-
catch (IOException)
58+
foreach (string dir in this.repoDirectories)
5259
{
53-
// This happens in AppVeyor a lot.
60+
try
61+
{
62+
TestUtilities.DeleteDirectory(dir);
63+
}
64+
catch (IOException)
65+
{
66+
// This happens in AppVeyor a lot.
67+
}
5468
}
5569
}
5670
}
@@ -107,7 +121,7 @@ protected Commit WriteVersionFile(VersionOptions versionData, string relativeDir
107121
}
108122

109123
string versionFilePath = VersionFile.SetVersion(Path.Combine(this.RepoPath, relativeDirectory), versionData);
110-
return this.CommitVersionFile(versionFilePath, versionData.Version.ToString());
124+
return this.CommitVersionFile(versionFilePath, versionData.Version?.ToString());
111125
}
112126

113127
protected Commit CommitVersionFile(string versionFilePath, string version)
@@ -129,7 +143,7 @@ protected Commit CommitVersionFile(string versionFilePath, string version)
129143
}
130144
}
131145

132-
return this.Repo.Commit($"Add/write {relativeFilePath} set to {version}", this.Signer, this.Signer, new CommitOptions { AllowEmptyCommit = true });
146+
return this.Repo.Commit($"Add/write {relativeFilePath} set to {version ?? "Inherited"}", this.Signer, this.Signer, new CommitOptions { AllowEmptyCommit = true });
133147
}
134148

135149
return null;

src/NerdBank.GitVersioning.Tests/VersionFileTests.cs

+135-9
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,8 @@ public void GetVersion_JsonCompatibility(string version, string assemblyVersion,
8888
Assert.NotNull(options);
8989
Assert.Equal(version, options.Version?.ToString());
9090
Assert.Equal(assemblyVersion, options.AssemblyVersion?.Version?.ToString());
91-
Assert.Equal(precision, options.AssemblyVersion?.Precision);
92-
Assert.Equal(buildNumberOffset, options.BuildNumberOffset);
91+
Assert.Equal(precision, options.AssemblyVersion?.PrecisionOrDefault);
92+
Assert.Equal(buildNumberOffset, options.BuildNumberOffsetOrDefault);
9393
Assert.Equal(publicReleaseRefSpec, options.PublicReleaseRefSpec);
9494
}
9595

@@ -114,17 +114,19 @@ public void SetVersion_GetVersionFromFile(string expectedVersion, string expecte
114114
}
115115

116116
[Theory]
117-
[InlineData("2.3", null, VersionOptions.VersionPrecision.Minor, 0, @"{""version"":""2.3""}")]
118-
[InlineData("2.3", "2.2", VersionOptions.VersionPrecision.Minor, 0, @"{""version"":""2.3"",""assemblyVersion"":""2.2""}")]
119-
[InlineData("2.3", "2.2", VersionOptions.VersionPrecision.Minor, -1, @"{""version"":""2.3"",""assemblyVersion"":""2.2"",""buildNumberOffset"":-1}")]
120-
[InlineData("2.3", "2.2", VersionOptions.VersionPrecision.Revision, -1, @"{""version"":""2.3"",""assemblyVersion"":{""version"":""2.2"",""precision"":""revision""},""buildNumberOffset"":-1}")]
121-
public void SetVersion_WritesSimplestFile(string version, string assemblyVersion, VersionOptions.VersionPrecision precision, int buildNumberOffset, string expectedJson)
117+
[InlineData("2.3", null, VersionOptions.VersionPrecision.Minor, 0, false, @"{""version"":""2.3""}")]
118+
[InlineData("2.3", null, VersionOptions.VersionPrecision.Minor, null, true, @"{""version"":""2.3"",""assemblyVersion"":{""precision"":""minor""},""inherit"":true}")]
119+
[InlineData("2.3", "2.2", VersionOptions.VersionPrecision.Minor, 0, false, @"{""version"":""2.3"",""assemblyVersion"":""2.2""}")]
120+
[InlineData("2.3", "2.2", VersionOptions.VersionPrecision.Minor, -1, false, @"{""version"":""2.3"",""assemblyVersion"":""2.2"",""buildNumberOffset"":-1}")]
121+
[InlineData("2.3", "2.2", VersionOptions.VersionPrecision.Revision, -1, false, @"{""version"":""2.3"",""assemblyVersion"":{""version"":""2.2"",""precision"":""revision""},""buildNumberOffset"":-1}")]
122+
public void SetVersion_WritesSimplestFile(string version, string assemblyVersion, VersionOptions.VersionPrecision? precision, int? buildNumberOffset, bool inherit, string expectedJson)
122123
{
123124
var versionOptions = new VersionOptions
124125
{
125126
Version = SemanticVersion.Parse(version),
126-
AssemblyVersion = new VersionOptions.AssemblyVersionOptions(assemblyVersion != null ? new Version(assemblyVersion) : null, precision),
127+
AssemblyVersion = assemblyVersion != null || precision != null ? new VersionOptions.AssemblyVersionOptions(assemblyVersion != null ? new Version(assemblyVersion) : null, precision) : null,
127128
BuildNumberOffset = buildNumberOffset,
129+
Inherit = inherit,
128130
};
129131
string pathWritten = VersionFile.SetVersion(this.RepoPath, versionOptions);
130132
string actualFileContent = File.ReadAllText(pathWritten);
@@ -142,7 +144,7 @@ public void SetVersion_WritesSimplestFile(string version, string assemblyVersion
142144
[InlineData(@"{""cloudBuild"":{""setVersionVariables"":true}}", @"{}")]
143145
public void JsonMinification(string full, string minimal)
144146
{
145-
var settings = VersionOptions.JsonSettings;
147+
var settings = VersionOptions.GetJsonSettings();
146148
settings.Formatting = Formatting.None;
147149

148150
// Assert that the two representations are equivalent.
@@ -271,6 +273,130 @@ public void GetVersion_String_MissingFile()
271273
Assert.Null(VersionFile.GetVersion(this.RepoPath));
272274
}
273275

276+
[Fact]
277+
public void VersionJson_InheritButNoParentFileFound()
278+
{
279+
this.InitializeSourceControl();
280+
this.WriteVersionFile(
281+
new VersionOptions
282+
{
283+
Inherit = true,
284+
Version = SemanticVersion.Parse("14.2"),
285+
});
286+
Assert.Throws<InvalidOperationException>(() => VersionFile.GetVersion(this.Repo));
287+
}
288+
289+
[Fact]
290+
public void VersionJson_DoNotInheritButNoVersionSpecified()
291+
{
292+
this.InitializeSourceControl();
293+
Assert.Throws<ArgumentException>(() => this.WriteVersionFile(
294+
new VersionOptions
295+
{
296+
Inherit = false,
297+
}));
298+
}
299+
300+
[Theory]
301+
[InlineData(false, false)]
302+
[InlineData(true, false)]
303+
[InlineData(true, true)]
304+
public void VersionJson_Inheritance(bool commitInSourceControl, bool bareRepo)
305+
{
306+
if (commitInSourceControl)
307+
{
308+
this.InitializeSourceControl();
309+
}
310+
311+
VersionOptions level1, level2, level3, level2NoInherit, level2InheritButResetVersion;
312+
this.WriteVersionFile(
313+
level1 = new VersionOptions
314+
{
315+
Version = SemanticVersion.Parse("14.2"),
316+
AssemblyVersion = new VersionOptions.AssemblyVersionOptions { Precision = VersionOptions.VersionPrecision.Major },
317+
});
318+
this.WriteVersionFile(
319+
level2 = new VersionOptions
320+
{
321+
Inherit = true,
322+
AssemblyVersion = new VersionOptions.AssemblyVersionOptions { Precision = VersionOptions.VersionPrecision.Minor },
323+
},
324+
"foo");
325+
this.WriteVersionFile(
326+
level3 = new VersionOptions
327+
{
328+
Inherit = true,
329+
BuildNumberOffset = 1,
330+
},
331+
@"foo\bar");
332+
this.WriteVersionFile(
333+
level2NoInherit = new VersionOptions
334+
{
335+
Version = SemanticVersion.Parse("10.1"),
336+
},
337+
@"noInherit");
338+
this.WriteVersionFile(
339+
level2InheritButResetVersion = new VersionOptions
340+
{
341+
Inherit = true,
342+
Version = SemanticVersion.Parse("8.2"),
343+
},
344+
@"inheritWithVersion");
345+
346+
Repository operatingRepo = this.Repo;
347+
if (bareRepo)
348+
{
349+
operatingRepo = new Repository(
350+
Repository.Clone(this.RepoPath, CreateDirectoryForNewRepo(), new CloneOptions { IsBare = true }));
351+
}
352+
353+
using (operatingRepo)
354+
{
355+
VersionOptions GetOption(string path) => commitInSourceControl ? VersionFile.GetVersion(operatingRepo, path) : VersionFile.GetVersion(Path.Combine(this.RepoPath, path));
356+
357+
var level1Options = GetOption(string.Empty);
358+
Assert.False(level1Options.Inherit);
359+
360+
var level2Options = GetOption("foo");
361+
Assert.Equal(level1.Version.Version.Major, level2Options.Version.Version.Major);
362+
Assert.Equal(level1.Version.Version.Minor, level2Options.Version.Version.Minor);
363+
Assert.Equal(level2.AssemblyVersion.Precision, level2Options.AssemblyVersion.Precision);
364+
Assert.True(level2Options.Inherit);
365+
366+
var level3Options = GetOption(@"foo\bar");
367+
Assert.Equal(level1.Version.Version.Major, level3Options.Version.Version.Major);
368+
Assert.Equal(level1.Version.Version.Minor, level3Options.Version.Version.Minor);
369+
Assert.Equal(level2.AssemblyVersion.Precision, level3Options.AssemblyVersion.Precision);
370+
Assert.Equal(level2.AssemblyVersion.Precision, level3Options.AssemblyVersion.Precision);
371+
Assert.Equal(level3.BuildNumberOffset, level3Options.BuildNumberOffset);
372+
Assert.True(level3Options.Inherit);
373+
374+
var level2NoInheritOptions = GetOption("noInherit");
375+
Assert.Equal(level2NoInherit.Version, level2NoInheritOptions.Version);
376+
Assert.Equal(VersionOptions.DefaultVersionPrecision, level2NoInheritOptions.AssemblyVersionOrDefault.PrecisionOrDefault);
377+
Assert.False(level2NoInheritOptions.Inherit);
378+
379+
var level2InheritButResetVersionOptions = GetOption("inheritWithVersion");
380+
Assert.Equal(level2InheritButResetVersion.Version, level2InheritButResetVersionOptions.Version);
381+
Assert.True(level2InheritButResetVersionOptions.Inherit);
382+
383+
if (commitInSourceControl)
384+
{
385+
int totalCommits = operatingRepo.Head.Commits.Count();
386+
387+
// The version height should be the same for all those that inherit the version from the base,
388+
// even though the inheriting files were introduced in successive commits.
389+
Assert.Equal(totalCommits, operatingRepo.GetVersionHeight());
390+
Assert.Equal(totalCommits, operatingRepo.GetVersionHeight("foo"));
391+
Assert.Equal(totalCommits, operatingRepo.GetVersionHeight(@"foo\bar"));
392+
393+
// These either don't inherit, or inherit but reset versions, so the commits were reset.
394+
Assert.Equal(2, operatingRepo.GetVersionHeight("noInherit"));
395+
Assert.Equal(1, operatingRepo.GetVersionHeight("inheritWithVersion"));
396+
}
397+
}
398+
}
399+
274400
private void AssertPathHasVersion(Commit commit, string absolutePath, VersionOptions expected)
275401
{
276402
var actual = VersionFile.GetVersion(absolutePath);

src/NerdBank.GitVersioning.Tests/VersionOptionsTests.cs

+21-7
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public void FromVersion()
1515
Assert.Equal(new Version(1, 2), vo.Version.Version);
1616
Assert.Equal("-pre", vo.Version.Prerelease);
1717
Assert.Null(vo.AssemblyVersion);
18-
Assert.Equal(0, vo.BuildNumberOffset);
18+
Assert.Equal(0, vo.BuildNumberOffsetOrDefault);
1919
}
2020

2121
[Fact]
@@ -100,7 +100,7 @@ public void CloudBuildOptions_Equality()
100100

101101
var cbo2a = new VersionOptions.CloudBuildOptions
102102
{
103-
SetVersionVariables = !cbo1a.SetVersionVariables,
103+
SetVersionVariables = !cbo1a.SetVersionVariablesOrDefault,
104104
};
105105
Assert.NotEqual(cbo2a, cbo1a);
106106

@@ -114,7 +114,7 @@ public void CloudBuildOptions_Equality()
114114
{
115115
BuildNumber = new VersionOptions.CloudBuildNumberOptions
116116
{
117-
Enabled = !(new VersionOptions.CloudBuildNumberOptions().Enabled),
117+
Enabled = !cbo1a.BuildNumberOrDefault.EnabledOrDefault,
118118
},
119119
};
120120
Assert.NotEqual(cbo4a, cbo1a);
@@ -129,7 +129,7 @@ public void CloudBuildNumberOptions_Equality()
129129

130130
var bno2a = new VersionOptions.CloudBuildNumberOptions
131131
{
132-
Enabled = !bno1a.Enabled,
132+
Enabled = !bno1a.EnabledOrDefault,
133133
};
134134
Assert.NotEqual(bno1a, bno2a);
135135

@@ -149,20 +149,34 @@ public void CloudBuildNumberOptions_Equality()
149149
[Fact]
150150
public void CloudBuildNumberCommitIdOptions_Equality()
151151
{
152-
var cio1a = new VersionOptions.CloudBuildNumberCommitIdOptions { };
152+
var cio1a = new VersionOptions.CloudBuildNumberCommitIdOptions();
153+
cio1a.Where = cio1a.WhereOrDefault;
154+
cio1a.When = cio1a.WhenOrDefault;
153155
var cio1b = new VersionOptions.CloudBuildNumberCommitIdOptions { };
154156
Assert.Equal(cio1a, cio1b);
155157

156158
var cio2a = new VersionOptions.CloudBuildNumberCommitIdOptions
157159
{
158-
When = (VersionOptions.CloudBuildNumberCommitWhen)((int)cio1a.When + 1),
160+
When = (VersionOptions.CloudBuildNumberCommitWhen)((int)cio1a.WhenOrDefault + 1),
159161
};
160162
Assert.NotEqual(cio1a, cio2a);
161163

162164
var cio3a = new VersionOptions.CloudBuildNumberCommitIdOptions
163165
{
164-
Where = (VersionOptions.CloudBuildNumberCommitWhere)((int)cio1a.Where + 1),
166+
Where = (VersionOptions.CloudBuildNumberCommitWhere)((int)cio1a.WhereOrDefault + 1),
165167
};
166168
Assert.NotEqual(cio1a, cio3a);
167169
}
170+
171+
[Fact]
172+
public void CannotWriteToDefaultInstances()
173+
{
174+
var options = new VersionOptions();
175+
Assert.Throws<InvalidOperationException>(() => options.AssemblyVersionOrDefault.Precision = VersionOptions.VersionPrecision.Revision);
176+
Assert.Throws<InvalidOperationException>(() => options.CloudBuildOrDefault.BuildNumberOrDefault.Enabled = true);
177+
Assert.Throws<InvalidOperationException>(() => options.CloudBuildOrDefault.BuildNumberOrDefault.IncludeCommitIdOrDefault.When = VersionOptions.CloudBuildNumberCommitWhen.Always);
178+
Assert.Throws<InvalidOperationException>(() => options.CloudBuildOrDefault.BuildNumberOrDefault.IncludeCommitIdOrDefault.Where = VersionOptions.CloudBuildNumberCommitWhere.BuildMetadata);
179+
Assert.Throws<InvalidOperationException>(() => options.CloudBuildOrDefault.SetVersionVariables = true);
180+
Assert.Throws<InvalidOperationException>(() => options.NuGetPackageVersionOrDefault.SemVer = 2);
181+
}
168182
}

src/NerdBank.GitVersioning.Tests/VersionSchemaTests.cs

+14
Original file line numberDiff line numberDiff line change
@@ -70,4 +70,18 @@ public void VersionField_HeightMacroPlacement()
7070
json = JObject.Parse(@"{ ""version"": ""2.3.0-beta+height-{height}"" }");
7171
Assert.False(json.IsValid(this.schema));
7272
}
73+
74+
[Fact]
75+
public void Inherit_AllowsOmissionOfVersion()
76+
{
77+
json = JObject.Parse(@"{ ""inherit"": false, ""version"": ""1.2"" }");
78+
Assert.True(json.IsValid(this.schema));
79+
json = JObject.Parse(@"{ ""inherit"": false }");
80+
Assert.False(json.IsValid(this.schema));
81+
json = JObject.Parse(@"{ }");
82+
Assert.False(json.IsValid(this.schema));
83+
84+
json = JObject.Parse(@"{ ""inherit"": true }");
85+
Assert.True(json.IsValid(this.schema));
86+
}
7387
}

0 commit comments

Comments
 (0)