Skip to content

Commit

Permalink
tagged version wins even if MinVerMinimumMajorMinor is higher
Browse files Browse the repository at this point in the history
  • Loading branch information
adamralph committed Aug 15, 2024
1 parent 2e48c6e commit 8b439a9
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 21 deletions.
25 changes: 16 additions & 9 deletions MinVer.Lib/Versioner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,33 +10,40 @@ public static Version GetVersion(string workDir, string tagPrefix, MajorMinor mi

var defaultPreReleaseIdentifiersList = defaultPreReleaseIdentifiers.ToList();

var (version, height) = GetVersion(workDir, tagPrefix, defaultPreReleaseIdentifiersList, log);
var (version, height, isFromTag) = GetVersion(workDir, tagPrefix, defaultPreReleaseIdentifiersList, log);

_ = height.HasValue && ignoreHeight && log.IsDebugEnabled && log.Debug("Ignoring height.");
version = !height.HasValue || ignoreHeight ? version : version.WithHeight(height.Value, autoIncrement, defaultPreReleaseIdentifiersList);

version = version.AddBuildMetadata(buildMeta);

var calculatedVersion = version.Satisfying(minMajorMinor, defaultPreReleaseIdentifiersList);
var ignoreMinMajorMinor = isFromTag && height is 0;

_ = calculatedVersion != version
? log.IsInfoEnabled && log.Info($"Bumping version to {calculatedVersion} to satisfy minimum major minor {minMajorMinor}.")
: log.IsDebugEnabled && log.Debug($"The calculated version {calculatedVersion} satisfies the minimum major minor {minMajorMinor}.");
var calculatedVersion =
ignoreMinMajorMinor
? version.Satisfying(MajorMinor.Default, defaultPreReleaseIdentifiersList)
: version.Satisfying(minMajorMinor, defaultPreReleaseIdentifiersList);

_ = ignoreMinMajorMinor
? minMajorMinor != MajorMinor.Default && log.IsDebugEnabled && log.Debug($"Ignoring minimum major minor {minMajorMinor} because the commit is tagged.")
: calculatedVersion != version
? log.IsInfoEnabled && log.Info($"Bumping version to {calculatedVersion} to satisfy minimum major minor {minMajorMinor}.")
: log.IsDebugEnabled && log.Debug($"The calculated version {calculatedVersion} satisfies the minimum major minor {minMajorMinor}.");

_ = log.IsInfoEnabled && log.Info($"Calculated version {calculatedVersion}.");

return calculatedVersion;
}

private static (Version Version, int? Height) GetVersion(string workDir, string tagPrefix, List<string> defaultPreReleaseIdentifiers, ILogger log)
private static (Version Version, int? Height, bool IsFromTag) GetVersion(string workDir, string tagPrefix, List<string> defaultPreReleaseIdentifiers, ILogger log)
{
if (!Git.IsWorkingDirectory(workDir, log))
{
var version = new Version(defaultPreReleaseIdentifiers);

_ = log.IsWarnEnabled && log.Warn(1001, $"'{workDir}' is not a valid Git working directory. Using default version {version}.");

return (version, default);
return (version, default, default);
}

if (!Git.TryGetHead(workDir, out var head, log))
Expand All @@ -45,7 +52,7 @@ private static (Version Version, int? Height) GetVersion(string workDir, string

_ = log.IsInfoEnabled && log.Info($"No commits found. Using default version {version}.");

return (version, default);
return (version, default, default);
}

var tags = Git.GetTags(workDir, log);
Expand All @@ -71,7 +78,7 @@ private static (Version Version, int? Height) GetVersion(string workDir, string
_ = string.IsNullOrEmpty(selectedCandidate.Tag) && log.IsInfoEnabled && log.Info($"No commit found with a valid SemVer 2.0 version{(string.IsNullOrEmpty(tagPrefix) ? "" : $" prefixed with '{tagPrefix}'")}. Using default version {selectedCandidate.Version}.");
_ = log.IsInfoEnabled && log.Info($"Using{(log.IsDebugEnabled && orderedCandidates.Count > 1 ? " " : " ")}{selectedCandidate.ToString(tagWidth, versionWidth, heightWidth)}.");

return (selectedCandidate.Version, selectedCandidate.Height);
return (selectedCandidate.Version, selectedCandidate.Height, !string.IsNullOrEmpty(selectedCandidate.Tag));
}

private static List<Candidate> GetCandidates(Commit head, IEnumerable<(string Name, string Sha)> tags, string tagPrefix, IReadOnlyCollection<string> defaultPreReleaseIdentifiers, ILogger log)
Expand Down
50 changes: 47 additions & 3 deletions MinVerTests.Lib/LogMessages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public static class LogMessages
[Theory]
[InlineData(0, 0)]
[InlineData(2, 0)]
public static async Task RepoWithHistory(int minMajor, int minMinor)
public static async Task MinimumMajorMinorAfterTag(int minMajor, int minMinor)
{
// arrange
var minMajorMinor = new MajorMinor(minMajor, minMinor);
Expand Down Expand Up @@ -67,8 +67,52 @@ git checkout main
_ = Versioner.GetVersion(path, "", minMajorMinor, "", default, PreReleaseIdentifiers.Default, false, log);

// assert
var logMessages = log.ToString();
var logMessages = await ReplaceShas(log.ToString(), path);

await AssertFile.Contains($"../../../log.{minMajorMinor}.txt", logMessages);
}

[Theory]
[InlineData(3, 0)]
public static async Task MinimumMajorMinorOnTag(int minMajor, int minMinor)
{
// arrange
var minMajorMinor = new MajorMinor(minMajor, minMinor);

var historicalCommands =
@"
git commit --allow-empty -m '.'
git tag not-a-version
git checkout -b foo
git commit --allow-empty -m '.'
git tag 1.0.0-foo.1
";

var path = MethodBase.GetCurrentMethod().GetTestDirectory(minMajorMinor);

await EnsureEmptyRepository(path);

foreach (var item in historicalCommands
.ToNonEmptyLines()
.Select((command, index) => new { Command = command, Index = $"{index}", }))
{
var nameAndArgs = item.Command.Split(" ", 2);
_ = await ReadAsync(nameAndArgs[0], nameAndArgs[1], path);
}

var log = new TestLogger();

// act
_ = Versioner.GetVersion(path, "", minMajorMinor, "", default, PreReleaseIdentifiers.Default, false, log);

// assert
var logMessages = await ReplaceShas(log.ToString(), path);

await AssertFile.Contains($"../../../log.{minMajorMinor}.txt", logMessages);
}

private static async Task<string> ReplaceShas(string logMessages, string path)
{
var shas = (await ReadAsync("git", "log --pretty=format:\"%H\"", path))
.StandardOutput
.ToNonEmptyLines()
Expand All @@ -85,6 +129,6 @@ git checkout main
logMessages = logMessages.Replace(item.ShortSha, $"{item.Index}", StringComparison.Ordinal);
}

await AssertFile.Contains($"../../../log.{minMajorMinor}.txt", logMessages);
return logMessages;
}
}
13 changes: 5 additions & 8 deletions MinVerTests.Lib/MinMajorMinor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ public static async Task NoCommits()
}

[Theory]
[InlineData("4.0.0", 3, 2, "4.0.0", true)]
[InlineData("4.3.0", 4, 3, "4.3.0", true)]
[InlineData("4.3.0", 5, 4, "5.4.0-alpha.0", false)]
public static async Task Tagged(string tag, int major, int minor, string expectedVersion, bool isRedundant)
[InlineData("4.0.0", 3, 2, "4.0.0")]
[InlineData("4.3.0", 4, 3, "4.3.0")]
[InlineData("4.3.0", 5, 4, "4.3.0")]
public static async Task Tagged(string tag, int major, int minor, string expectedVersion)
{
// arrange
var path = MethodBase.GetCurrentMethod().GetTestDirectory((tag, major, minor));
Expand All @@ -41,10 +41,7 @@ public static async Task Tagged(string tag, int major, int minor, string expecte
// assert
Assert.Equal(expectedVersion, actualVersion.ToString());

if (isRedundant)
{
Assert.Contains(logger.Messages, message => message.Text.Contains($"The calculated version {actualVersion} satisfies the minimum major minor {major}.{minor}.", StringComparison.Ordinal));
}
Assert.Contains(logger.Messages, message => message.Text.Contains($"Ignoring minimum major minor {major}.{minor} because the commit is tagged.", StringComparison.Ordinal));
}

[Fact]
Expand Down
32 changes: 32 additions & 0 deletions MinVerTests.Lib/log.3.0.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
Trace: Running Git: git status --short
Trace: Git exit code: 0
Trace: Git stdout:
?? command-read-00.md
?? command-read-01.md
?? command-read-02.md
?? command-read-03.md

Trace: Git stderr:

Trace: Running Git: git log --pretty=format:"%H %P"
Trace: Git exit code: 0
Trace: Git stdout:
1 0
0
Trace: Git stderr:

Trace: Running Git: git show-ref --tags --dereference
Trace: Git exit code: 0
Trace: Git stdout:
1 refs/tags/1.0.0-foo.1
0 refs/tags/not-a-version

Trace: Git stderr:

Debug: Ignoring non-version tag { Name: not-a-version, Sha: 0 }.
Trace: Checking commit 1 (height 0)...
Trace: Found version tag { Commit: 1, Tag: '1.0.0-foo.1', Version: 1.0.0-foo.1, Height: 0 }.
Debug: 1 commits checked.
Info: Using { Commit: 1, Tag: '1.0.0-foo.1', Version: 1.0.0-foo.1, Height: 0 }.
Debug: Ignoring minimum major minor 3.0 because the commit is tagged.
Info: Calculated version 1.0.0-foo.1.
2 changes: 1 addition & 1 deletion MinVerTests.Packages/MinimumMajorMinorOnTag.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public static async Task HasMinimumMajorMinor()

var envVars = ("MinVerMinimumMajorMinor".ToAltCase(), "3.0");

var expected = Package.WithVersion(3, 0, 0, ["alpha", "0",]);
var expected = Package.WithVersion(2, 3, 4);

// act
var (actual, _, _) = await Sdk.BuildProject(path, envVars: envVars);
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@ Note that `MinVerMinimumMajorMinor` will be redundant after you create the first

Also note that if the latest version tag found in the commit history has a higher `MAJOR.MINOR` than `MinVerMinimumMajorMinor`, then `MinVerMinimumMajorMinor` will be ignored.

Lastly, if the the current commit has a version tag, the tag will be used as-is, even if it has a lower `MAJOR.MINOR` than `MinVerMinimumMajorMinor`.

### Can I use my own pre-release versioning scheme?

Yes! MinVer doesn't care what your pre-release versioning scheme is. The default pre-release identifiers are `alpha.0`, but you can use whatever you like in your tags. If your versioning scheme is valid [SemVer 2.x](https://semver.org/spec/v2.0.0.html), it will work with MinVer.
Expand Down

0 comments on commit 8b439a9

Please sign in to comment.