diff --git a/GitVersion.sln.GhostDoc.xml b/GitVersion.sln.GhostDoc.xml index f671bde190..81bf4da447 100644 --- a/GitVersion.sln.GhostDoc.xml +++ b/GitVersion.sln.GhostDoc.xml @@ -23,6 +23,7 @@ false false true + true false diff --git a/GitVersionCore.Tests/GitFlow/MetaDataByCommitFixture.cs b/GitVersionCore.Tests/GitFlow/MetaDataByCommitFixture.cs index e10a27902a..957a9ab8d9 100644 --- a/GitVersionCore.Tests/GitFlow/MetaDataByCommitFixture.cs +++ b/GitVersionCore.Tests/GitFlow/MetaDataByCommitFixture.cs @@ -1,8 +1,6 @@ - using System; - using GitVersion; - using LibGit2Sharp; - using NUnit.Framework; - using Shouldly; +using LibGit2Sharp; +using NUnit.Framework; +using Shouldly; [TestFixture] public class MetaDataByCommitFixture @@ -33,65 +31,56 @@ public void CanCorrectlyDetectCommitCountsAndReleaseDataWhenThatApplies() using (var f = new CommitCountingRepoFixture()) { ResetToP(f.Repository); - EnsureMetaDataMatch(f, "develop", "1.4.0-unstable.7+7"); + EnsureMetaDataMatch(f, "1.4.0-unstable.7+7"); ResetToO(f.Repository); - EnsureMetaDataMatch(f, "develop", "1.4.0-unstable.6+6"); + EnsureMetaDataMatch(f, "1.4.0-unstable.6+6"); ResetToN(f.Repository); - EnsureMetaDataMatch(f, "master", "1.3.1", r => (Commit) r.Tags["1.3.0"].Target); + EnsureMetaDataMatch(f, "1.3.1"); ResetToM(f.Repository); - EnsureMetaDataMatch(f, "develop", "1.4.0-unstable.5+5"); + EnsureMetaDataMatch(f, "1.4.0-unstable.5+5"); ResetToL(f.Repository); - EnsureMetaDataMatch(f, "hotfix-1.3.1", "1.3.1-beta.1+1", r => (Commit) r.Tags["1.3.0"].Target); + EnsureMetaDataMatch(f, "1.3.1-beta.1+1"); ResetToK(f.Repository); - EnsureMetaDataMatch(f, "feature", "1.4.0-feature+2"); + EnsureMetaDataMatch(f, "1.4.0-feature+2"); ResetToJ(f.Repository); - EnsureMetaDataMatch(f, "feature", "1.4.0-feature+1"); + EnsureMetaDataMatch(f, "1.4.0-feature+1"); ResetToI(f.Repository); - EnsureMetaDataMatch(f, "develop", "1.4.0-unstable.2+2"); + EnsureMetaDataMatch(f, "1.4.0-unstable.2+2"); ResetToH(f.Repository); - EnsureMetaDataMatch(f, "master", "1.3.0", r => (Commit) r.Tags["1.3.0"].Target); + EnsureMetaDataMatch(f, "1.3.0"); ResetToG(f.Repository); - EnsureMetaDataMatch(f, "release-1.3.0", "1.3.0-beta.1+2"); + EnsureMetaDataMatch(f, "1.3.0-beta.1+2"); ResetToF(f.Repository); - EnsureMetaDataMatch(f, "master", "1.2.1", r => (Commit) r.Tags["1.2.0"].Target); + EnsureMetaDataMatch(f, "1.2.1"); ResetToE(f.Repository); - EnsureMetaDataMatch(f, "develop", "1.3.0-unstable.2+2"); + EnsureMetaDataMatch(f, "1.3.0-unstable.2+2"); ResetToD(f.Repository); - EnsureMetaDataMatch(f, "release-1.3.0", "1.3.0-beta.1+1"); + EnsureMetaDataMatch(f, "1.3.0-beta.1+1"); ResetToC(f.Repository); - EnsureMetaDataMatch(f, "hotfix-1.2.1", "1.2.1-beta.1+1", r => (Commit) r.Tags["1.2.0"].Target); + EnsureMetaDataMatch(f, "1.2.1-beta.1+1"); ResetToB(f.Repository); - EnsureMetaDataMatch(f, "develop", "1.3.0-unstable.1+1"); + EnsureMetaDataMatch(f, "1.3.0-unstable.1+1"); } } - static void EnsureMetaDataMatch( - CommitCountingRepoFixture fixture, string branchName, - string expectedSemVer, Func commitFinder = null) + static void EnsureMetaDataMatch(CommitCountingRepoFixture fixture,string expectedSemVer) { - - var referenceCommitFinder = commitFinder ?? (r => r.FindBranch(branchName).Tip); - - var commit = referenceCommitFinder(fixture.Repository); - var result = fixture.ExecuteGitVersion(); result.ToString("f").ShouldBe(expectedSemVer); - result.BuildMetaData.ReleaseDate.OriginalCommitSha.ShouldBe(commit.Sha); - result.BuildMetaData.ReleaseDate.OriginalDate.ShouldBe(commit.Committer.When); } void DropTags(IRepository repo, params string[] names) diff --git a/GitVersionCore.Tests/GitVersionCore.Tests.csproj b/GitVersionCore.Tests/GitVersionCore.Tests.csproj index 9e0d70416c..c7eefb60d8 100644 --- a/GitVersionCore.Tests/GitVersionCore.Tests.csproj +++ b/GitVersionCore.Tests/GitVersionCore.Tests.csproj @@ -78,6 +78,7 @@ + diff --git a/GitVersionCore.Tests/InformationalVersionBuilderTests.cs b/GitVersionCore.Tests/InformationalVersionBuilderTests.cs index 803b1717b4..d88d1bda32 100644 --- a/GitVersionCore.Tests/InformationalVersionBuilderTests.cs +++ b/GitVersionCore.Tests/InformationalVersionBuilderTests.cs @@ -1,3 +1,4 @@ +using System; using GitVersion; using NUnit.Framework; @@ -24,7 +25,7 @@ public void ValidateInformationalVersionBuilder(BranchType branchType, string br Minor = minor, Patch = patch, PreReleaseTag = tag, - BuildMetaData = new SemanticVersionBuildMetaData(suffix, branchName, new ReleaseDate{ CommitSha = sha }), + BuildMetaData = new SemanticVersionBuildMetaData(suffix, branchName,sha,DateTimeOffset.MinValue), }; var informationalVersion = semanticVersion.ToString("i"); diff --git a/GitVersionCore.Tests/JsonVersionBuilderTests.Json.approved.txt b/GitVersionCore.Tests/JsonVersionBuilderTests.Json.approved.txt index a4b985e9ee..58e95e63e8 100644 --- a/GitVersionCore.Tests/JsonVersionBuilderTests.Json.approved.txt +++ b/GitVersionCore.Tests/JsonVersionBuilderTests.Json.approved.txt @@ -17,7 +17,6 @@ "ClassicVersionWithTag":"1.2.3.5-unstable.4", "BranchName":"feature1", "Sha":"commitSha", - "OriginalRelease":"originalCommitSha.2014-03-01 00:00:01Z", "NuGetVersionV2":"1.2.3-unstable0004", "NuGetVersion":"1.2.3-unstable0004" } \ No newline at end of file diff --git a/GitVersionCore.Tests/JsonVersionBuilderTests.cs b/GitVersionCore.Tests/JsonVersionBuilderTests.cs index 2a64106644..42101b0f3b 100644 --- a/GitVersionCore.Tests/JsonVersionBuilderTests.cs +++ b/GitVersionCore.Tests/JsonVersionBuilderTests.cs @@ -15,14 +15,7 @@ public void Json() Minor = 2, Patch = 3, PreReleaseTag = "unstable4", - BuildMetaData = new SemanticVersionBuildMetaData(5, "feature1", - new ReleaseDate - { - OriginalCommitSha = "originalCommitSha", - OriginalDate = DateTimeOffset.Parse("2014-03-01 00:00:01Z"), - CommitSha = "commitSha", - Date = DateTimeOffset.Parse("2014-03-06 23:59:59Z") - }) + BuildMetaData = new SemanticVersionBuildMetaData(5, "feature1", "commitSha",DateTimeOffset.Parse("2014-03-06 23:59:59Z")) }; var variables = VariableProvider.GetVariablesFor(semanticVersion); var json = JsonOutputFormatter.ToJson(variables); diff --git a/GitVersionCore.Tests/LastVersionOnMasterFinderTests.cs b/GitVersionCore.Tests/LastVersionOnMasterFinderTests.cs new file mode 100644 index 0000000000..aca2cde437 --- /dev/null +++ b/GitVersionCore.Tests/LastVersionOnMasterFinderTests.cs @@ -0,0 +1,214 @@ + using System; + using GitVersion; + using LibGit2Sharp; + using NUnit.Framework; + using Shouldly; + +[TestFixture] +public class LastVersionOnMasterFinderTests +{ + /* + * hotfix-1.2.1 -----------C-- + * / \ + * master A----------------F-----H-------N + * \ / \ / + * hotfix-1.3.1 \ / ----L + * \ / \ + * release-1.3.0 \ -D----G--- \ + * \ / \ \ + * develop -----B----E-------I-----M--O--P + * \ / + * feature -------J-K- + * + * + * - A is tagged `1.2.0` + * - F is tagged `1.2.1` + * - H is tagged `1.3.0` + * - N is tagged `1.3.1` + */ + + [Test] + public void CanCorrectlyDetectCommitCountsAndReleaseDataWhenThatApplies() + { + using (var f = new CommitCountingRepoFixture()) + { + ResetToP(f.Repository); + EnsureMetaDataMatch(f, "develop"); + + ResetToO(f.Repository); + EnsureMetaDataMatch(f, "develop"); + + ResetToN(f.Repository); + EnsureMetaDataMatch(f, "master", r => (Commit) r.Tags["1.3.0"].Target); + + ResetToM(f.Repository); + EnsureMetaDataMatch(f, "develop"); + + ResetToL(f.Repository); + EnsureMetaDataMatch(f, "hotfix-1.3.1", r => (Commit) r.Tags["1.3.0"].Target); + + ResetToK(f.Repository); + EnsureMetaDataMatch(f, "feature"); + + ResetToJ(f.Repository); + EnsureMetaDataMatch(f, "feature"); + + ResetToI(f.Repository); + EnsureMetaDataMatch(f, "develop"); + + ResetToH(f.Repository); + EnsureMetaDataMatch(f, "master", r => (Commit) r.Tags["1.3.0"].Target); + + ResetToG(f.Repository); + EnsureMetaDataMatch(f, "release-1.3.0"); + + ResetToF(f.Repository); + EnsureMetaDataMatch(f, "master", r => (Commit) r.Tags["1.2.0"].Target); + + ResetToE(f.Repository); + EnsureMetaDataMatch(f, "develop"); + + ResetToD(f.Repository); + EnsureMetaDataMatch(f, "release-1.3.0"); + + ResetToC(f.Repository); + EnsureMetaDataMatch(f, "hotfix-1.2.1", r => (Commit) r.Tags["1.2.0"].Target); + + ResetToB(f.Repository); + EnsureMetaDataMatch(f, "develop"); + } + } + + static void EnsureMetaDataMatch(CommitCountingRepoFixture fixture, string branchName, Func commitFinder = null) + { + var referenceCommitFinder = commitFinder ?? (r => r.FindBranch(branchName).Tip); + + var commit = referenceCommitFinder(fixture.Repository); + var releaseDate = LastVersionOnMasterFinder.Execute(fixture.Repository, commit); + releaseDate.ShouldBe(commit.When()); + } + + void DropTags(IRepository repo, params string[] names) + { + foreach (var name in names) + { + if (repo.Tags[name] == null) + { + continue; + } + + repo.Tags.Remove(name); + } + } + + void DropBranches(IRepository repo, params string[] names) + { + foreach (var name in names) + { + if (repo.Branches[name] == null) + { + continue; + } + + repo.Branches.Remove(name); + } + } + + void ResetBranch(IRepository repo, string name, string committish) + { + var b = repo.Branches[name]; + Assert.NotNull(b); + repo.Refs.UpdateTarget(b.CanonicalName, committish); + } + + void ResetToP(IRepository repo) + { + ResetBranch(repo, "develop", "4d65c519f88773854f9345eaf5dbb30cb49f6a74"); + } + + void ResetToO(IRepository repo) + { + ResetBranch(repo, "develop", "7655537837096d925a4f974232f78ec589d86ebd"); + } + + void ResetToN(IRepository repo) + { + ResetBranch(repo, "develop", "0b7a2482ab7d167cefa4ecfc106db001dc5c17ff"); + repo.Refs.UpdateTarget("HEAD", "refs/heads/master"); + } + + void ResetToM(IRepository repo) + { + ResetBranch(repo, "develop", "0b7a2482ab7d167cefa4ecfc106db001dc5c17ff"); + ResetBranch(repo, "master", "5b84136c848fd48f1f8b3fa4e1b767a1f6101279"); + DropTags(repo, "1.3.1"); + repo.Refs.UpdateTarget("HEAD", "refs/heads/develop"); + } + + void ResetToL(IRepository repo) + { + ResetBranch(repo, "develop", "243f56dcdb543688fd0a99bd3e0e72dd9a786603"); + repo.Refs.UpdateTarget("HEAD", "refs/heads/hotfix-1.3.1"); + } + + void ResetToK(IRepository repo) + { + repo.Refs.UpdateTarget("HEAD", "refs/heads/feature"); + DropBranches(repo, "hotfix-1.3.1"); + } + + void ResetToJ(IRepository repo) + { + ResetBranch(repo, "feature", "0491c5dac30d706f4e54c5cb26d082baad8228d1"); + } + + void ResetToI(IRepository repo) + { + repo.Refs.UpdateTarget("HEAD", "refs/heads/develop"); + DropBranches(repo, "feature"); + } + + void ResetToH(IRepository repo) + { + ResetBranch(repo, "develop", "320f4b6820cf4b0853dc08ac153f04fbd4958200"); + repo.Refs.UpdateTarget("HEAD", "refs/heads/master"); + } + + void ResetToG(IRepository repo) + { + ResetBranch(repo, "master", "576a28e321cd6dc764b52c5fface672fa076f37f"); + repo.Refs.UpdateTarget("HEAD", "refs/heads/release-1.3.0"); + DropTags(repo, "1.3.0"); + } + + void ResetToF(IRepository repo) + { + ResetBranch(repo, "release-1.3.0", "b53054c614d36edc9d1bee8c35cd2ed575a43607"); + repo.Refs.UpdateTarget("HEAD", "refs/heads/master"); + } + + void ResetToE(IRepository repo) + { + ResetBranch(repo, "master", "8c890487ed143d5a72d151e64be1c5ddb314c908"); + repo.Refs.UpdateTarget("HEAD", "refs/heads/develop"); + DropTags(repo, "1.2.1"); + } + + void ResetToD(IRepository repo) + { + ResetBranch(repo, "develop", "fab69e28ee35dd912c0c95d5993dd84e4f2bcd92"); + repo.Refs.UpdateTarget("HEAD", "refs/heads/release-1.3.0"); + } + + void ResetToC(IRepository repo) + { + repo.Refs.UpdateTarget("HEAD", "refs/heads/hotfix-1.2.1"); + DropBranches(repo, "release-1.3.0"); + } + + void ResetToB(IRepository repo) + { + repo.Refs.UpdateTarget("HEAD", "refs/heads/develop"); + DropBranches(repo, "hotfix-1.2.1"); + } +} \ No newline at end of file diff --git a/GitVersionCore.Tests/SemanticVersionTests.cs b/GitVersionCore.Tests/SemanticVersionTests.cs index d6ef94cb21..b3820eeb36 100644 --- a/GitVersionCore.Tests/SemanticVersionTests.cs +++ b/GitVersionCore.Tests/SemanticVersionTests.cs @@ -67,14 +67,6 @@ public void VersionSorting() SemanticVersion.Parse("1.0.0").ShouldBeGreaterThan(SemanticVersion.Parse("1.0.0-beta")); } - [Test] - public void EmptyVersion() - { - Assert.IsTrue(SemanticVersion.Empty.IsEmpty()); - - var emptyVersion = new SemanticVersion(); - Assert.IsTrue(emptyVersion.IsEmpty()); - } [Test] public void ToStringJTests() { diff --git a/GitVersionCore.Tests/ShortVersionParserTests.cs b/GitVersionCore.Tests/ShortVersionParserTests.cs index cabb47bc68..d6072e90f7 100644 --- a/GitVersionCore.Tests/ShortVersionParserTests.cs +++ b/GitVersionCore.Tests/ShortVersionParserTests.cs @@ -8,8 +8,7 @@ public class ShortVersionParserTests [Test] public void Major_minor_patch() { - ShortVersion shortVersion; - ShortVersionParser.Parse("1.2.3", out shortVersion); + var shortVersion = ShortVersionParser.Parse("1.2.3"); Assert.AreEqual(1, shortVersion.Major); Assert.AreEqual(2, shortVersion.Minor); Assert.AreEqual(3, shortVersion.Patch); diff --git a/GitVersionCore.Tests/VariableProviderTests.cs b/GitVersionCore.Tests/VariableProviderTests.cs index 78a7d3809c..efc969edbc 100644 --- a/GitVersionCore.Tests/VariableProviderTests.cs +++ b/GitVersionCore.Tests/VariableProviderTests.cs @@ -18,13 +18,9 @@ public void DevelopBranchFormatsSemVerForCiFeed() BuildMetaData = "5.Branch.develop" }; - semVer.BuildMetaData.ReleaseDate = new ReleaseDate - { - OriginalCommitSha = "originalCommitSha", - OriginalDate = DateTimeOffset.Parse("2014-03-01 00:00:01Z"), - CommitSha = "commitSha", - Date = DateTimeOffset.Parse("2014-03-06 23:59:59Z") - }; + semVer.BuildMetaData.Sha = "commitSha"; + semVer.BuildMetaData.CommitDate = DateTimeOffset.Parse("2014-03-06 23:59:59Z"); + var vars = VariableProvider.GetVariablesFor(semVer); diff --git a/GitVersionCore/BuildServers/AppVeyor.cs b/GitVersionCore/BuildServers/AppVeyor.cs index 67a513933e..6a5eb7a3ed 100644 --- a/GitVersionCore/BuildServers/AppVeyor.cs +++ b/GitVersionCore/BuildServers/AppVeyor.cs @@ -65,7 +65,7 @@ public override string[] GenerateSetParameterMessage(string name, string value) return new[] { - string.Format("Adding Environment Variable. name='GitVersion.{0}' value='{1}']", name, value), + string.Format("Adding Environment Variable. name='GitVersion.{0}' value='{1}']", name, value) }; } } diff --git a/GitVersionCore/BuildServers/GitHelper.cs b/GitVersionCore/BuildServers/GitHelper.cs index 2e58d25a86..53f9800329 100644 --- a/GitVersionCore/BuildServers/GitHelper.cs +++ b/GitVersionCore/BuildServers/GitHelper.cs @@ -73,17 +73,27 @@ public static bool LooksLikeAValidPullRequestNumber(string issueNumber) public static string ExtractIssueNumber(string mergeMessage) { + // Dynamic: refs/heads/pr/5 // Github Message: refs/heads/pull/5/merge // Stash Message: refs/heads/pull-requests/5/merge - var regex = new Regex(MergeMessageRegexPattern); - var match = regex.Match(mergeMessage); + // Note by @GeertvanHorrik: sorry, I suck at regex so did a quick hack, feel free to replace by regex + if (mergeMessage.Contains("refs/heads/pr/")) + { + var issueNumber = mergeMessage.Replace("refs/heads/pr/", string.Empty); + return issueNumber; + } + else + { + var regex = new Regex(MergeMessageRegexPattern); + var match = regex.Match(mergeMessage); - string issueNumber = null; + string issueNumber = null; - issueNumber = match.Groups["issuenumber"].Value; + issueNumber = match.Groups["issuenumber"].Value; - return issueNumber; + return issueNumber; + } } static void AddMissingRefSpecs(Repository repo, Remote remote) diff --git a/GitVersionCore/CachedVersion.cs b/GitVersionCore/CachedVersion.cs deleted file mode 100644 index ae100101f4..0000000000 --- a/GitVersionCore/CachedVersion.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace GitVersion -{ - class CachedVersion - { - public SemanticVersion SemanticVersion; - public long Timestamp; - } -} diff --git a/GitVersionCore/DirectoryDateFinder.cs b/GitVersionCore/DirectoryDateFinder.cs deleted file mode 100644 index bc8ef58a34..0000000000 --- a/GitVersionCore/DirectoryDateFinder.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace GitVersion -{ - using System; - using System.IO; - - static class DirectoryDateFinder - { - public static long GetLastDirectoryWrite(string path) - { - var lastHigh = DateTime.MinValue; - foreach (var file in Directory.EnumerateDirectories(path, "*.*", SearchOption.AllDirectories)) - { - var lastWriteTime = File.GetLastWriteTime(file); - if (lastWriteTime > lastHigh) - { - lastHigh = lastWriteTime; - } - } - return lastHigh.Ticks; - } - } -} \ No newline at end of file diff --git a/GitVersionCore/ExtensionMethods.cs b/GitVersionCore/Extensions/ExtensionMethods.cs similarity index 98% rename from GitVersionCore/ExtensionMethods.cs rename to GitVersionCore/Extensions/ExtensionMethods.cs index dc658d7928..55c36d2381 100644 --- a/GitVersionCore/ExtensionMethods.cs +++ b/GitVersionCore/Extensions/ExtensionMethods.cs @@ -6,7 +6,7 @@ namespace GitVersion using System.Text.RegularExpressions; using JetBrains.Annotations; - static class ExtensionMethods + static partial class ExtensionMethods { public static bool IsOdd(this int number) { diff --git a/GitVersionCore/Extensions/ExtensionMethods.git.cs b/GitVersionCore/Extensions/ExtensionMethods.git.cs new file mode 100644 index 0000000000..9fb298023c --- /dev/null +++ b/GitVersionCore/Extensions/ExtensionMethods.git.cs @@ -0,0 +1,86 @@ +namespace GitVersion +{ + using System; + + static partial class ExtensionMethods + { + public static string GetCanonicalBranchName(this string branchName) + { + if (branchName.IsPullRequest()) + { + branchName = branchName.Replace("pull-requests", "pull"); + branchName = branchName.Replace("pr", "pull"); + + return string.Format("refs/{0}/head", branchName); + } + + return string.Format("refs/heads/{0}", branchName); + } + + public static bool IsHotfix(this string branchName) + { + return branchName.StartsWith("hotfix-") || branchName.StartsWith("hotfix/"); + } + + public static string GetHotfixSuffix(this string branchName) + { + return branchName.TrimStart("hotfix-").TrimStart("hotfix/"); + } + + public static bool IsRelease(this string branchName) + { + return branchName.StartsWith("release-") || branchName.StartsWith("release/"); + } + + public static string GetReleaseSuffix(this string branchName) + { + return branchName.TrimStart("release-").TrimStart("release/"); + } + + public static string GetUnknownBranchSuffix(this string branchName) + { + var unknownBranchSuffix = branchName.Split('-', '/'); + if (unknownBranchSuffix.Length == 1) + return branchName; + return unknownBranchSuffix[1]; + } + + public static string GetSuffix(this string branchName, BranchType branchType) + { + switch (branchType) + { + case BranchType.Hotfix: + return branchName.GetHotfixSuffix(); + + case BranchType.Release: + return branchName.GetReleaseSuffix(); + + case BranchType.Unknown: + return branchName.GetUnknownBranchSuffix(); + + default: + throw new NotSupportedException(string.Format("Unexpected branch type {0}.", branchType)); + } + } + + public static bool IsDevelop(this string branchName) + { + return branchName == "develop"; + } + + public static bool IsMaster(this string branchName) + { + return branchName == "master"; + } + + public static bool IsPullRequest(this string branchName) + { + return branchName.Contains("pull/") || branchName.Contains("pull-requests/") || branchName.Contains("pr/"); + } + + public static bool IsSupport(this string branchName) + { + return branchName.ToLower().StartsWith("support-"); + } + } +} diff --git a/GitVersionCore/GitFlow/BranchClassifier.cs b/GitVersionCore/GitFlow/BranchClassifier.cs index 9754de68f5..5c7c3c7101 100644 --- a/GitVersionCore/GitFlow/BranchClassifier.cs +++ b/GitVersionCore/GitFlow/BranchClassifier.cs @@ -1,75 +1,57 @@ namespace GitVersion { - using System; using LibGit2Sharp; static class BranchClassifier { - public static bool IsHotfix(this Branch branch) { - return branch.Name.StartsWith("hotfix-") || branch.Name.StartsWith("hotfix/"); + return branch.Name.IsHotfix(); } public static string GetHotfixSuffix(this Branch branch) { - return branch.Name.TrimStart("hotfix-").TrimStart("hotfix/"); + return branch.Name.GetHotfixSuffix(); } public static bool IsRelease(this Branch branch) { - return branch.Name.StartsWith("release-") || branch.Name.StartsWith("release/"); + return branch.Name.IsRelease(); } public static string GetReleaseSuffix(this Branch branch) { - return branch.Name.TrimStart("release-").TrimStart("release/"); + return branch.Name.GetReleaseSuffix(); } public static string GetUnknownBranchSuffix(this Branch branch) { - var unknownBranchSuffix = branch.Name.Split('-', '/'); - if (unknownBranchSuffix.Length == 1) - return branch.Name; - return unknownBranchSuffix[1]; + return branch.Name.GetUnknownBranchSuffix(); } public static string GetSuffix(this Branch branch, BranchType branchType) { - switch (branchType) - { - case BranchType.Hotfix: - return branch.GetHotfixSuffix(); - - case BranchType.Release: - return branch.GetReleaseSuffix(); - - case BranchType.Unknown: - return branch.GetUnknownBranchSuffix(); - - default: - throw new NotSupportedException(string.Format("Unexpected branch type {0}.", branchType)); - } + return branch.CanonicalName.GetSuffix(branchType); } public static bool IsDevelop(this Branch branch) { - return branch.Name == "develop"; + return branch.Name.IsDevelop(); } public static bool IsMaster(this Branch branch) { - return branch.Name == "master"; + return branch.Name.IsMaster(); } public static bool IsPullRequest(this Branch branch) { - return branch.CanonicalName.Contains("/pull/") || branch.CanonicalName.Contains("/pull-requests/"); + return branch.CanonicalName.IsPullRequest(); } public static bool IsSupport(this Branch branch) { - return branch.Name.ToLower().StartsWith("support-"); + return branch.Name.IsSupport(); } } } diff --git a/GitVersionCore/GitFlow/BranchFinders/BranchCommitDifferenceFinder.cs b/GitVersionCore/GitFlow/BranchFinders/BranchCommitDifferenceFinder.cs new file mode 100644 index 0000000000..0828ba7eaa --- /dev/null +++ b/GitVersionCore/GitFlow/BranchFinders/BranchCommitDifferenceFinder.cs @@ -0,0 +1,38 @@ +namespace GitVersion +{ + using System.Linq; + using LibGit2Sharp; + + static class BranchCommitDifferenceFinder + { + public static int NumberOfCommitsInBranchNotKnownFromBaseBranch(IRepository repo, Branch branch, BranchType branchType, string baseBranchName) + { + var baseTip = repo.FindBranch(baseBranchName).Tip; + if (branch.Tip == baseTip) + { + // The branch bears no additional commit + return 0; + } + + var ancestor = repo.Commits.FindMergeBase( + baseTip, + branch.Tip); + + if (ancestor == null) + { + var message = string.Format("A {0} branch is expected to branch off of '{1}'. However, branch '{1}' and '{2}' do not share a common ancestor.", branchType, baseBranchName, branch.Name); + throw new WarningException(message); + } + + var filter = new CommitFilter + { + Since = branch.Tip, + Until = ancestor, + SortBy = CommitSortStrategies.Topological | CommitSortStrategies.Time + }; + + return repo.Commits.QueryBy(filter) + .Count(); + } + } +} \ No newline at end of file diff --git a/GitVersionCore/GitFlow/BranchFinders/DevelopBasedVersionFinderBase.cs b/GitVersionCore/GitFlow/BranchFinders/DevelopBasedVersionFinderBase.cs index c0a9e76165..fd841647e7 100644 --- a/GitVersionCore/GitFlow/BranchFinders/DevelopBasedVersionFinderBase.cs +++ b/GitVersionCore/GitFlow/BranchFinders/DevelopBasedVersionFinderBase.cs @@ -18,11 +18,9 @@ protected SemanticVersion FindVersion( } var versionOnMasterFinder = new VersionOnMasterFinder(); - var versionFromMaster = versionOnMasterFinder.Execute(context, context.CurrentCommit.Committer.When); + var versionFromMaster = versionOnMasterFinder.Execute(context, context.CurrentCommit.When()); var numberOfCommitsOnBranchSinceCommit = NumberOfCommitsOnBranchSinceCommit(context, ancestor); - var sha = context.CurrentCommit.Sha; - var releaseDate = ReleaseDateFinder.Execute(context.Repository, sha, 0); var preReleaseTag = context.CurrentBranch.Name .TrimStart(branchType.ToString() + '-') .TrimStart(branchType.ToString() + '/'); @@ -34,7 +32,7 @@ protected SemanticVersion FindVersion( PreReleaseTag = preReleaseTag, BuildMetaData = new SemanticVersionBuildMetaData( numberOfCommitsOnBranchSinceCommit, - context.CurrentBranch.Name, releaseDate) + context.CurrentBranch.Name, context.CurrentCommit.Sha, context.CurrentCommit.When()) }; semanticVersion.OverrideVersionManuallyIfNeeded(context.Repository); diff --git a/GitVersionCore/GitFlow/BranchFinders/DevelopVersionFinder.cs b/GitVersionCore/GitFlow/BranchFinders/DevelopVersionFinder.cs index f6e60196a8..9f6a1e80f3 100644 --- a/GitVersionCore/GitFlow/BranchFinders/DevelopVersionFinder.cs +++ b/GitVersionCore/GitFlow/BranchFinders/DevelopVersionFinder.cs @@ -21,14 +21,13 @@ public SemanticVersion FindVersion(GitVersionContext context) var c = context.Repository.Commits.QueryBy(f); var numberOfCommitsSinceRelease = c.Count(); - var releaseDate = ReleaseDateFinder.Execute(context.Repository, tip.Sha, 0); var semanticVersion = new SemanticVersion { Major = versionFromMaster.Major, Minor = versionFromMaster.Minor + 1, Patch = 0, PreReleaseTag = "unstable" + numberOfCommitsSinceRelease, - BuildMetaData = new SemanticVersionBuildMetaData(numberOfCommitsSinceRelease, context.CurrentBranch.Name, releaseDate), + BuildMetaData = new SemanticVersionBuildMetaData(numberOfCommitsSinceRelease, context.CurrentBranch.Name,tip.Sha,tip.When()), }; semanticVersion.OverrideVersionManuallyIfNeeded(context.Repository); diff --git a/GitVersionCore/GitFlow/BranchFinders/HotfixVersionFinder.cs b/GitVersionCore/GitFlow/BranchFinders/HotfixVersionFinder.cs index 5e9d9bb291..5af628acc4 100644 --- a/GitVersionCore/GitFlow/BranchFinders/HotfixVersionFinder.cs +++ b/GitVersionCore/GitFlow/BranchFinders/HotfixVersionFinder.cs @@ -1,10 +1,52 @@ namespace GitVersion { - class HotfixVersionFinder : OptionallyTaggedBranchVersionFinderBase + using System.Linq; + using LibGit2Sharp; + + class HotfixVersionFinder { public SemanticVersion FindVersion(GitVersionContext context) { - return FindVersion(context, BranchType.Hotfix, "master"); + var versionString = GetSuffix(context.CurrentBranch); + var shortVersion = ShortVersionParser.Parse(versionString); + + EnsureVersionIsValid(shortVersion, context.CurrentBranch); + + var nbHotfixCommits = BranchCommitDifferenceFinder.NumberOfCommitsInBranchNotKnownFromBaseBranch(context.Repository, context.CurrentBranch, BranchType.Hotfix, "master"); + + var semanticVersionPreReleaseTag = GetSemanticVersionPreReleaseTag(context, shortVersion, nbHotfixCommits); + return new SemanticVersion + { + Major = shortVersion.Major, + Minor = shortVersion.Minor, + Patch = shortVersion.Patch, + PreReleaseTag = semanticVersionPreReleaseTag, + BuildMetaData = new SemanticVersionBuildMetaData(nbHotfixCommits, context.CurrentBranch.Name, context.CurrentCommit.Sha, context.CurrentCommit.When()) + }; + } + + static string GetSemanticVersionPreReleaseTag(GitVersionContext context, ShortVersion shortVersion, int nbHotfixCommits) + { + var semanticVersionPreReleaseTag = "beta.1"; + var tagVersion = RecentTagVersionExtractor.RetrieveMostRecentOptionalTagVersion(context.Repository, shortVersion, context.CurrentBranch.Commits.Take(nbHotfixCommits + 1)); + if (tagVersion != null) + { + semanticVersionPreReleaseTag = tagVersion; + } + return semanticVersionPreReleaseTag; + } + + static string GetSuffix(Branch branch) + { + return branch.Name.TrimStart("hotfix-").TrimStart("hotfix/"); + } + void EnsureVersionIsValid(ShortVersion version, Branch branch) + { + if (version.Patch == 0) + { + var message = string.Format("Branch '{0}' doesn't respect the Hotfix branch naming convention. A patch segment different than zero is required.", branch.Name); + throw new WarningException(message); + } } } } diff --git a/GitVersionCore/GitFlow/BranchFinders/MasterVersionFinder.cs b/GitVersionCore/GitFlow/BranchFinders/MasterVersionFinder.cs index a31e736cba..0389df20d2 100644 --- a/GitVersionCore/GitFlow/BranchFinders/MasterVersionFinder.cs +++ b/GitVersionCore/GitFlow/BranchFinders/MasterVersionFinder.cs @@ -11,35 +11,26 @@ public SemanticVersion FindVersion(IRepository repository, Commit tip) ShortVersion shortVersion; if (ShortVersionParser.TryParse(tag.Name, out shortVersion)) { - return BuildVersion(repository, tip, shortVersion); + return BuildVersion(tip, shortVersion); } } - var semanticVersion = new SemanticVersion(); - ShortVersion versionFromTip; if (MergeMessageParser.TryParse(tip, out versionFromTip)) { - semanticVersion = BuildVersion(repository, tip, versionFromTip); + return BuildVersion(tip, versionFromTip); } - - if (semanticVersion == null || semanticVersion.IsEmpty()) - { - throw new WarningException("The head of master should always be a merge commit if you follow gitflow. Please create one or work around this by tagging the commit with SemVer compatible Id."); - } - - return semanticVersion; + throw new WarningException("The head of master should always be a merge commit if you follow gitflow. Please create one or work around this by tagging the commit with SemVer compatible Id."); } - SemanticVersion BuildVersion(IRepository repository, Commit tip, ShortVersion shortVersion) + SemanticVersion BuildVersion(Commit tip, ShortVersion shortVersion) { - var releaseDate = ReleaseDateFinder.Execute(repository, tip.Sha, shortVersion.Patch); return new SemanticVersion { Major = shortVersion.Major, Minor = shortVersion.Minor, Patch = shortVersion.Patch, - BuildMetaData = new SemanticVersionBuildMetaData(null, "master", releaseDate) + BuildMetaData = new SemanticVersionBuildMetaData(null, "master",tip.Sha,tip.When()) }; } } diff --git a/GitVersionCore/GitFlow/BranchFinders/OptionallyTaggedBranchVersionFinderBase.cs b/GitVersionCore/GitFlow/BranchFinders/OptionallyTaggedBranchVersionFinderBase.cs deleted file mode 100644 index 5a0fa3daef..0000000000 --- a/GitVersionCore/GitFlow/BranchFinders/OptionallyTaggedBranchVersionFinderBase.cs +++ /dev/null @@ -1,174 +0,0 @@ -namespace GitVersion -{ - using System; - using System.Collections.Generic; - using System.Linq; - using LibGit2Sharp; - - abstract class OptionallyTaggedBranchVersionFinderBase - { - protected SemanticVersion FindVersion( - GitVersionContext context, - BranchType branchType, - string baseBranchName) - { - var nbHotfixCommits = NumberOfCommitsInBranchNotKnownFromBaseBranch(context.Repository, context.CurrentBranch, branchType, baseBranchName); - - var versionString = context.CurrentBranch.GetSuffix(branchType); - if (!versionString.Contains(".")) - return new SemanticVersion(); - var version = SemanticVersion.Parse(versionString); - - EnsureVersionIsValid(version, context.CurrentBranch, branchType); - - if (branchType == BranchType.Hotfix) - version.PreReleaseTag = "beta.1"; - if (branchType == BranchType.Release) - version.PreReleaseTag = "beta.1"; - if (branchType == BranchType.Unknown) - version.PreReleaseTag = context.CurrentBranch.Name.Replace("-" + versionString, string.Empty) + ".1"; - - var tagVersion = RetrieveMostRecentOptionalTagVersion(context.Repository, version, context.CurrentBranch.Commits.Take(nbHotfixCommits + 1)); - - var sha = context.CurrentCommit.Sha; - var releaseDate = ReleaseDateFinder.Execute(context.Repository, sha, version.Patch); - var semanticVersion = new SemanticVersion - { - Major = version.Major, - Minor = version.Minor, - Patch = version.Patch, - PreReleaseTag = version.PreReleaseTag, - BuildMetaData = new SemanticVersionBuildMetaData( - nbHotfixCommits, context.CurrentBranch.Name, releaseDate) - }; - - if (tagVersion != null) - { - //If the tag is on the eact commit then dont bump the PreReleaseTag - if (context.CurrentCommit.Sha != tagVersion.Commit.Sha) - { - tagVersion.SemVer.PreReleaseTag.Number++; - } - semanticVersion.PreReleaseTag = tagVersion.SemVer.PreReleaseTag; - } - - return semanticVersion; - } - - bool IsMostRecentCommitTagged(GitVersionContext context, out SemanticVersion version) - { - var currentCommit = context.CurrentBranch.Commits.First(); - - var tags = context.Repository.Tags - .Where(tag => tag.PeeledTarget() == currentCommit) - .ToList(); - - foreach (var tag in tags) - { - if (SemanticVersion.TryParse(tag.Name, out version)) - { - return true; - } - } - - version = null; - return false; - } - - VersionTaggedCommit RetrieveMostRecentOptionalTagVersion( - IRepository repository, SemanticVersion branchVersion, IEnumerable take) - { - foreach (var commit in take) - { - foreach (var tag in repository.TagsByDate(commit)) - { - SemanticVersion version; - if (!SemanticVersion.TryParse(tag.Name, out version)) - { - continue; - } - - if (branchVersion.Major != version.Major || - branchVersion.Minor != version.Minor || - branchVersion.Patch != version.Patch) - { - continue; - } - - return new VersionTaggedCommit(commit, version); - } - } - - return null; - } - - void EnsureVersionIsValid(SemanticVersion version, Branch branch, BranchType branchType) - { - var msg = string.Format("Branch '{0}' doesn't respect the {1} branch naming convention. ", - branch.Name, branchType); - - if (version.PreReleaseTag.HasTag()) - { - throw new WarningException(msg + string.Format("Supported format is '{0}-Major.Minor.Patch'.", branchType.ToString().ToLowerInvariant())); - } - - switch (branchType) - { - case BranchType.Hotfix: - if (version.Patch == 0) - { - throw new WarningException(msg + "A patch segment different than zero is required."); - } - - break; - - case BranchType.Release: - if (version.Patch != 0) - { - throw new WarningException(msg + "A patch segment equals to zero is required."); - } - - break; - - case BranchType.Unknown: - break; - - default: - throw new NotSupportedException(string.Format("Unexpected branch type {0}.", branchType)); - } - } - - int NumberOfCommitsInBranchNotKnownFromBaseBranch( - IRepository repo, - Branch branch, - BranchType branchType, - string baseBranchName) - { - var baseTip = repo.FindBranch(baseBranchName).Tip; - if (branch.Tip == baseTip) - { - // The branch bears no additional commit - return 0; - } - - var ancestor = repo.Commits.FindMergeBase( - baseTip, - branch.Tip); - - if (ancestor == null) - { - var message = string.Format("A {0} branch is expected to branch off of '{1}'. However, branch '{1}' and '{2}' do not share a common ancestor.", branchType, baseBranchName, branch.Name); - throw new WarningException(message); - } - - var filter = new CommitFilter - { - Since = branch.Tip, - Until = ancestor, - SortBy = CommitSortStrategies.Topological | CommitSortStrategies.Time - }; - - return repo.Commits.QueryBy(filter).Count(); - } - } -} \ No newline at end of file diff --git a/GitVersionCore/GitFlow/BranchFinders/RecentTagVersionExtractor.cs b/GitVersionCore/GitFlow/BranchFinders/RecentTagVersionExtractor.cs new file mode 100644 index 0000000000..49fe3e8a28 --- /dev/null +++ b/GitVersionCore/GitFlow/BranchFinders/RecentTagVersionExtractor.cs @@ -0,0 +1,46 @@ +namespace GitVersion +{ + using System.Collections.Generic; + using LibGit2Sharp; + + class RecentTagVersionExtractor + { + internal static SemanticVersionPreReleaseTag RetrieveMostRecentOptionalTagVersion(IRepository repository, ShortVersion matchVersion, IEnumerable take) + { + Commit first = null; + foreach (var commit in take) + { + if (first == null) + { + first = commit; + } + foreach (var tag in repository.TagsByDate(commit)) + { + SemanticVersion version; + if (!SemanticVersion.TryParse(tag.Name, out version)) + { + continue; + } + + if (matchVersion.Major == version.Major && + matchVersion.Minor == version.Minor && + matchVersion.Patch == version.Patch) + { + var preReleaseTag = version.PreReleaseTag; + + //If the tag is on the eact commit then dont bump the PreReleaseTag + if (first != commit) + { + preReleaseTag.Number++; + } + return preReleaseTag; + } + } + } + + return null; + } + + + } +} \ No newline at end of file diff --git a/GitVersionCore/GitFlow/BranchFinders/ReleaseVersionFinder.cs b/GitVersionCore/GitFlow/BranchFinders/ReleaseVersionFinder.cs index 88d7839716..04fa53515e 100644 --- a/GitVersionCore/GitFlow/BranchFinders/ReleaseVersionFinder.cs +++ b/GitVersionCore/GitFlow/BranchFinders/ReleaseVersionFinder.cs @@ -1,10 +1,48 @@ namespace GitVersion { - class ReleaseVersionFinder : OptionallyTaggedBranchVersionFinderBase + using System.Linq; + using LibGit2Sharp; + + class ReleaseVersionFinder { public SemanticVersion FindVersion(GitVersionContext context) { - return FindVersion(context, BranchType.Release, "develop"); + var versionString = GetSuffix(context.CurrentBranch); + var shortVersion = ShortVersionParser.Parse(versionString); + + EnsureVersionIsValid(shortVersion, context.CurrentBranch); + var semanticVersionPreReleaseTag = "beta.1"; + + var nbHotfixCommits = BranchCommitDifferenceFinder.NumberOfCommitsInBranchNotKnownFromBaseBranch(context.Repository, context.CurrentBranch, BranchType.Release, "develop"); + + var tagVersion = RecentTagVersionExtractor.RetrieveMostRecentOptionalTagVersion(context.Repository, shortVersion, context.CurrentBranch.Commits.Take(nbHotfixCommits + 1)); + if (tagVersion != null) + { + semanticVersionPreReleaseTag = tagVersion; + } + return new SemanticVersion + { + Major = shortVersion.Major, + Minor = shortVersion.Minor, + Patch = shortVersion.Patch, + PreReleaseTag = semanticVersionPreReleaseTag, + BuildMetaData = new SemanticVersionBuildMetaData(nbHotfixCommits, context.CurrentBranch.Name, context.CurrentCommit.Sha, context.CurrentCommit.When()) + }; + } + + void EnsureVersionIsValid(ShortVersion version, Branch branch) + { + if (version.Patch != 0) + { + var message = string.Format("Branch '{0}' doesn't respect the Release branch naming convention. A patch segment equals to zero is required.", branch.Name); + throw new WarningException(message); + } + + } + + static string GetSuffix(Branch branch) + { + return branch.Name.TrimStart("release-").TrimStart("release/"); } } } diff --git a/GitVersionCore/GitFlow/BranchFinders/SupportVersionFinder.cs b/GitVersionCore/GitFlow/BranchFinders/SupportVersionFinder.cs index aa8dc88712..256ee7753a 100644 --- a/GitVersionCore/GitFlow/BranchFinders/SupportVersionFinder.cs +++ b/GitVersionCore/GitFlow/BranchFinders/SupportVersionFinder.cs @@ -8,40 +8,31 @@ public SemanticVersion FindVersion(IRepository repository, Commit tip) { foreach (var tag in repository.TagsByDate(tip)) { - ShortVersion shortVersion; - if (ShortVersionParser.TryParse(tag.Name, out shortVersion)) + ShortVersion shortVersion; + if (ShortVersionParser.TryParse(tag.Name, out shortVersion)) { - return BuildVersion(repository, tip, shortVersion); + return BuildVersion(tip, shortVersion); } } - var semanticVersion = new SemanticVersion(); - ShortVersion versionFromTip; if (MergeMessageParser.TryParse(tip, out versionFromTip)) { - semanticVersion = BuildVersion(repository, tip, versionFromTip); - } - - semanticVersion.OverrideVersionManuallyIfNeeded(repository); - - if (semanticVersion == null || semanticVersion.IsEmpty()) - { - throw new WarningException("The head of a support branch should always be a merge commit if you follow gitflow. Please create one or work around this by tagging the commit with SemVer compatible Id."); + var semanticVersion = BuildVersion(tip, versionFromTip); + semanticVersion.OverrideVersionManuallyIfNeeded(repository); + return semanticVersion; } - - return semanticVersion; + throw new WarningException("The head of a support branch should always be a merge commit if you follow gitflow. Please create one or work around this by tagging the commit with SemVer compatible Id."); } - SemanticVersion BuildVersion(IRepository repository, Commit tip, ShortVersion shortVersion) + SemanticVersion BuildVersion(Commit tip, ShortVersion shortVersion) { - var releaseDate = ReleaseDateFinder.Execute(repository, tip.Sha, shortVersion.Patch); return new SemanticVersion { Major = shortVersion.Major, Minor = shortVersion.Minor, Patch = shortVersion.Patch, - BuildMetaData = new SemanticVersionBuildMetaData(null, "support", releaseDate) + BuildMetaData = new SemanticVersionBuildMetaData(null, "support", tip.Sha,tip.When()) }; } } diff --git a/GitVersionCore/GitFlow/BranchFinders/VersionOnMasterFinder.cs b/GitVersionCore/GitFlow/BranchFinders/VersionOnMasterFinder.cs new file mode 100644 index 0000000000..7ed71a044a --- /dev/null +++ b/GitVersionCore/GitFlow/BranchFinders/VersionOnMasterFinder.cs @@ -0,0 +1,47 @@ +namespace GitVersion +{ + using System; + + class VersionOnMasterFinder + { + public VersionPoint Execute(GitVersionContext context, DateTimeOffset olderThan) + { + var masterBranch = context.Repository.FindBranch("master"); + foreach (var commit in masterBranch.CommitsPriorToThan(olderThan)) + { + foreach (var tag in context.Repository.TagsByDate(commit)) + { + ShortVersion shortVersion; + if (ShortVersionParser.TryParseMajorMinor(tag.Name, out shortVersion)) + { + return new VersionPoint + { + Major = shortVersion.Major, + Minor = shortVersion.Minor, + }; + } + } + + ShortVersion shortVersionFromMergeMessage; + if (MergeMessageParser.TryParse(commit, out shortVersionFromMergeMessage)) + { + return new VersionPoint + { + Major = shortVersionFromMergeMessage.Major, + Minor = shortVersionFromMergeMessage.Minor, + }; + } + } + return new VersionPoint + { + Major = 0, + Minor = 1, + }; + } + + + + + + } +} diff --git a/GitVersionCore/GitHubFlow/BuildNumberCalculator.cs b/GitVersionCore/GitHubFlow/BuildNumberCalculator.cs index 39a9435295..fb5d3e6b59 100644 --- a/GitVersionCore/GitHubFlow/BuildNumberCalculator.cs +++ b/GitVersionCore/GitHubFlow/BuildNumberCalculator.cs @@ -19,16 +19,11 @@ public BuildNumberCalculator(NextSemverCalculator nextSemverCalculator, LastTagg public SemanticVersion GetBuildNumber(GitVersionContext context) { - var commit = lastTaggedReleaseFinder.GetVersion().Commit; - var commitsSinceLastRelease = NumberOfCommitsOnBranchSinceCommit(context, commit); + var commitsSinceLastRelease = GetCommitsSinceLastRelease(context); var semanticVersion = nextSemverCalculator.NextVersion(); - var sha = context.CurrentCommit.Sha; - var releaseDate = ReleaseDateFinder.Execute(context.Repository, sha, semanticVersion.Patch); - // TODO Need a way of setting this in a cross cutting way - semanticVersion.BuildMetaData = new SemanticVersionBuildMetaData(commitsSinceLastRelease, - context.CurrentBranch.Name, releaseDate); + semanticVersion.BuildMetaData = new SemanticVersionBuildMetaData(commitsSinceLastRelease, context.CurrentBranch.Name, context.CurrentCommit.Sha, context.CurrentCommit.When()); if (context.CurrentBranch.IsPullRequest()) { EnsurePullBranchShareACommonAncestorWithMaster(gitRepo, gitRepo.Head); @@ -40,6 +35,21 @@ public SemanticVersion GetBuildNumber(GitVersionContext context) return semanticVersion; } + int GetCommitsSinceLastRelease(GitVersionContext context) + { + int commitsSinceLastRelease; + VersionTaggedCommit versionTaggedCommit; + if (lastTaggedReleaseFinder.GetVersion(out versionTaggedCommit)) + { + commitsSinceLastRelease = NumberOfCommitsOnBranchSinceCommit(context, versionTaggedCommit.Commit); + } + else + { + commitsSinceLastRelease = NumberOfCommitsOnBranchSinceCommit(context, context.CurrentBranch.Commits.Last()); + } + return commitsSinceLastRelease; + } + int NumberOfCommitsOnBranchSinceCommit(GitVersionContext context, Commit commit) { var qf = new CommitFilter diff --git a/GitVersionCore/GitHubFlow/LastTaggedReleaseFinder.cs b/GitVersionCore/GitHubFlow/LastTaggedReleaseFinder.cs index 21bde8c04a..9c6acccb53 100644 --- a/GitVersionCore/GitHubFlow/LastTaggedReleaseFinder.cs +++ b/GitVersionCore/GitHubFlow/LastTaggedReleaseFinder.cs @@ -1,24 +1,18 @@ namespace GitVersion { - using System; using System.Linq; using LibGit2Sharp; public class LastTaggedReleaseFinder { - Lazy lastTaggedRelease; + GitVersionContext context; public LastTaggedReleaseFinder(GitVersionContext context) { - lastTaggedRelease = new Lazy(() => GetVersion(context)); + this.context = context; } - public VersionTaggedCommit GetVersion() - { - return lastTaggedRelease.Value; - } - - VersionTaggedCommit GetVersion(GitVersionContext context) + public bool GetVersion(out VersionTaggedCommit versionTaggedCommit) { var tags = context.Repository.Tags.Select(t => { @@ -31,15 +25,18 @@ VersionTaggedCommit GetVersion(GitVersionContext context) }) .Where(a => a != null) .ToArray(); - var olderThan = context.CurrentCommit.Committer.When; + var olderThan = context.CurrentCommit.When(); var lastTaggedCommit = - context.CurrentBranch.Commits.FirstOrDefault(c => c.Committer.When <= olderThan && tags.Any(a => a.Commit == c)); + context.CurrentBranch.Commits.FirstOrDefault(c => c.When() <= olderThan && tags.Any(a => a.Commit == c)); if (lastTaggedCommit != null) - return tags.Last(a => a.Commit.Sha == lastTaggedCommit.Sha); + { + versionTaggedCommit = tags.Last(a => a.Commit.Sha == lastTaggedCommit.Sha); + return true; + } - var commit = context.CurrentBranch.Commits.Last(); - return new VersionTaggedCommit(commit, new SemanticVersion()); + versionTaggedCommit = null; + return false; } } } \ No newline at end of file diff --git a/GitVersionCore/GitHubFlow/MergedBranchesWithVersionFinder.cs b/GitVersionCore/GitHubFlow/MergedBranchesWithVersionFinder.cs index dbee4e1687..db0e46a7c3 100644 --- a/GitVersionCore/GitHubFlow/MergedBranchesWithVersionFinder.cs +++ b/GitVersionCore/GitHubFlow/MergedBranchesWithVersionFinder.cs @@ -1,24 +1,18 @@ namespace GitVersion { - using System; using System.Collections.Generic; using System.Linq; public class MergedBranchesWithVersionFinder { - Lazy lastMergedBranchWithVersion; + GitVersionContext context; public MergedBranchesWithVersionFinder(GitVersionContext context) { - lastMergedBranchWithVersion = new Lazy(() => GetVersion(context)); + this.context = context; } - public SemanticVersion GetVersion() - { - return lastMergedBranchWithVersion.Value; - } - - SemanticVersion GetVersion(GitVersionContext context) + public bool TryGetVersion(out SemanticVersion semanticVersion) { var shortVersion = GetAllVersions(context) .OrderBy(x=>x.Major) @@ -26,14 +20,16 @@ SemanticVersion GetVersion(GitVersionContext context) .LastOrDefault(); if (shortVersion == null) { - return null; + semanticVersion = null; + return false; } - return new SemanticVersion + semanticVersion =new SemanticVersion { Major = shortVersion.Major, Minor = shortVersion.Minor, Patch = shortVersion.Patch }; + return true; } static IEnumerable GetAllVersions(GitVersionContext context) diff --git a/GitVersionCore/GitHubFlow/NextSemverCalculator.cs b/GitVersionCore/GitHubFlow/NextSemverCalculator.cs index 02f0bda892..888e5d1bf0 100644 --- a/GitVersionCore/GitHubFlow/NextSemverCalculator.cs +++ b/GitVersionCore/GitHubFlow/NextSemverCalculator.cs @@ -1,5 +1,6 @@ namespace GitVersion { + using System.Collections.Generic; using System.Linq; public class NextSemverCalculator @@ -24,40 +25,55 @@ public NextSemverCalculator( public SemanticVersion NextVersion() { - var versionZero = new SemanticVersion(); - var lastRelease = lastTaggedReleaseFinder.GetVersion(); - var fileVersion = nextVersionTxtFileFinder.GetNextVersion(); - var mergedBranchVersion = mergedBranchesWithVersionFinder.GetVersion(); - var otherBranchVersion = unknownBranchFinder.FindVersion(context); - if (otherBranchVersion != null && otherBranchVersion.PreReleaseTag != null && otherBranchVersion.PreReleaseTag.Name == "release") - otherBranchVersion.PreReleaseTag.Name = "beta"; + var versions = GetPossibleVersions().ToList(); - var maxCalculated = new[] { fileVersion, otherBranchVersion, mergedBranchVersion }.Max(); + if (versions.Any()) + { + return versions.Max(); + } + return new SemanticVersion + { + Minor = 1 + }; + } - if (lastRelease.SemVer == versionZero && maxCalculated == versionZero) + public IEnumerable GetPossibleVersions() + { + + VersionTaggedCommit lastTaggedRelease; + if (lastTaggedReleaseFinder.GetVersion(out lastTaggedRelease)) { - return new SemanticVersion + //If the exact commit is tagged then just return that commit + if (context.CurrentCommit.Sha == lastTaggedRelease.Commit.Sha) { - Minor = 1 - }; + yield return lastTaggedRelease.SemVer; + yield break; + } + yield return new SemanticVersion + { + Major = lastTaggedRelease.SemVer.Major, + Minor = lastTaggedRelease.SemVer.Minor, + Patch = lastTaggedRelease.SemVer.Patch + 1 + }; } - if (string.Equals(context.CurrentCommit.Sha, lastRelease.Commit.Sha)) + SemanticVersion fileVersion; + if (nextVersionTxtFileFinder.TryGetNextVersion(out fileVersion)) + { + yield return fileVersion; + } + SemanticVersion tryGetVersion; + if (mergedBranchesWithVersionFinder.TryGetVersion(out tryGetVersion)) { - return lastRelease.SemVer; + yield return tryGetVersion; } - if (maxCalculated <= lastRelease.SemVer) + SemanticVersion otherBranchVersion; + if (unknownBranchFinder.FindVersion(context, out otherBranchVersion)) { - return new SemanticVersion - { - Major = lastRelease.SemVer.Major, - Minor = lastRelease.SemVer.Minor, - Patch = lastRelease.SemVer.Patch + 1 - }; + yield return otherBranchVersion; } - return maxCalculated; } } } \ No newline at end of file diff --git a/GitVersionCore/GitHubFlow/NextVersionTxtFileFinder.cs b/GitVersionCore/GitHubFlow/NextVersionTxtFileFinder.cs index 7c9e8bb23a..e36ea77cdc 100644 --- a/GitVersionCore/GitHubFlow/NextVersionTxtFileFinder.cs +++ b/GitVersionCore/GitHubFlow/NextVersionTxtFileFinder.cs @@ -12,27 +12,29 @@ public NextVersionTxtFileFinder(string repositoryDirectory) this.repositoryDirectory = repositoryDirectory; } - public SemanticVersion GetNextVersion() + public bool TryGetNextVersion(out SemanticVersion semanticVersion) { var filePath = Path.Combine(repositoryDirectory, "NextVersion.txt"); if (!File.Exists(filePath)) { - return new SemanticVersion(); + semanticVersion = null; + return false; } var version = File.ReadAllText(filePath); if (string.IsNullOrEmpty(version)) { - return new SemanticVersion(); + semanticVersion = null; + return false; } - SemanticVersion semanticVersion; if (!SemanticVersion.TryParse(version, out semanticVersion)) { throw new ArgumentException("Make sure you have a valid semantic version in NextVersion.txt"); } - return semanticVersion; + + return true; } } } \ No newline at end of file diff --git a/GitVersionCore/GitHubFlow/OtherBranchVersionFinder.cs b/GitVersionCore/GitHubFlow/OtherBranchVersionFinder.cs index 4074f83956..0ca5a9e84c 100644 --- a/GitVersionCore/GitHubFlow/OtherBranchVersionFinder.cs +++ b/GitVersionCore/GitHubFlow/OtherBranchVersionFinder.cs @@ -1,19 +1,53 @@ namespace GitVersion { - using System; + using System.Linq; + using LibGit2Sharp; - class OtherBranchVersionFinder : OptionallyTaggedBranchVersionFinderBase + class OtherBranchVersionFinder { - public SemanticVersion FindVersion(GitVersionContext context) + public bool FindVersion(GitVersionContext context, out SemanticVersion semanticVersion) { - try + var versionString = GetUnknownBranchSuffix(context.CurrentBranch); + if (!versionString.Contains(".")) { - return FindVersion(context, BranchType.Unknown, "master"); + semanticVersion = null; + return false; } - catch (Exception) + var shortVersion = ShortVersionParser.Parse(versionString); + + SemanticVersionPreReleaseTag semanticVersionPreReleaseTag = context.CurrentBranch.Name.Replace("-" + versionString, string.Empty) + ".1"; + + var nbHotfixCommits = BranchCommitDifferenceFinder.NumberOfCommitsInBranchNotKnownFromBaseBranch(context.Repository, context.CurrentBranch, BranchType.Unknown, "master"); + + var tagVersion = RecentTagVersionExtractor.RetrieveMostRecentOptionalTagVersion(context.Repository, shortVersion, context.CurrentBranch.Commits.Take(nbHotfixCommits + 1)); + if (tagVersion != null) + { + semanticVersionPreReleaseTag = tagVersion; + } + + if (semanticVersionPreReleaseTag.Name == "release") { - return new SemanticVersion(); + semanticVersionPreReleaseTag.Name = "beta"; } + + semanticVersion = new SemanticVersion + { + Major = shortVersion.Major, + Minor = shortVersion.Minor, + Patch = shortVersion.Patch, + PreReleaseTag = semanticVersionPreReleaseTag, + BuildMetaData = new SemanticVersionBuildMetaData(nbHotfixCommits, context.CurrentBranch.Name, context.CurrentCommit.Sha, context.CurrentCommit.When()) + }; + return true; + } + + static string GetUnknownBranchSuffix(Branch branch) + { + var unknownBranchSuffix = branch.Name.Split('-', '/'); + if (unknownBranchSuffix.Length == 1) + return branch.Name; + return unknownBranchSuffix[1]; } + } } \ No newline at end of file diff --git a/GitVersionCore/GitVersionCore.csproj b/GitVersionCore/GitVersionCore.csproj index cab6cfa83c..e3073e75f3 100644 --- a/GitVersionCore/GitVersionCore.csproj +++ b/GitVersionCore/GitVersionCore.csproj @@ -63,12 +63,15 @@ - - + + + + + - + @@ -76,7 +79,6 @@ - @@ -104,16 +106,12 @@ - - - - diff --git a/GitVersionCore/GitVersionFinder.cs b/GitVersionCore/GitVersionFinder.cs index 97b7f3c6fe..dacd80ef95 100644 --- a/GitVersionCore/GitVersionFinder.cs +++ b/GitVersionCore/GitVersionFinder.cs @@ -19,7 +19,15 @@ public SemanticVersion FindVersion(GitVersionContext context) return new GitFlowVersionFinder().FindVersion(context); } - public static bool ShouldGitHubFlowVersioningSchemeApply(IRepository repo) + public static SemanticVersion GetSemanticVersion(Repository repository) + { + var versionForRepositoryFinder = new GitVersionFinder(); + var gitVersionContext = new GitVersionContext(repository); + Logger.WriteInfo("Running against branch: " + gitVersionContext.CurrentBranch.Name); + return versionForRepositoryFinder.FindVersion(gitVersionContext); + } + + static bool ShouldGitHubFlowVersioningSchemeApply(IRepository repo) { return repo.FindBranch("develop") == null; } diff --git a/GitVersionCore/LastVersionOnMasterFinder.cs b/GitVersionCore/LastVersionOnMasterFinder.cs new file mode 100644 index 0000000000..5733eec251 --- /dev/null +++ b/GitVersionCore/LastVersionOnMasterFinder.cs @@ -0,0 +1,94 @@ +using System.Collections.Generic; +using System.Linq; +using LibGit2Sharp; + +namespace GitVersion +{ + using System; + + public class LastVersionOnMasterFinder + { + public static DateTimeOffset Execute(IRepository repo, Commit commit) + { + //dont need an if for release since we want the current date for a release branch + if ( + repo.Head.IsMaster() || + repo.Head.IsHotfix() + ) + { + var vp = FindLatestStableTaggedCommitReachableFrom(repo, commit); + return vp.When(); + } + return commit.When(); + } + + static Commit FindLatestStableTaggedCommitReachableFrom(IRepository repo, Commit commit) + { + var masterTip = repo.FindBranch("master").Tip; + var ancestor = repo.Commits.FindMergeBase(masterTip, commit); + + var allTags = repo.Tags.ToList(); + + foreach (var c in repo.Commits.QueryBy(new CommitFilter + { + Since = ancestor.Id, + SortBy = CommitSortStrategies.Topological | CommitSortStrategies.Time + } + )) + { + var vp = RetrieveStableVersionPointFor(allTags, c); + + if (vp != null) + { + return vp; + } + } + + return null; + } + + static Commit RetrieveStableVersionPointFor(IEnumerable allTags, Commit c) + { + var tags = allTags + .Where(tag => tag.PeeledTarget() == c) + .Where(tag => IsStableRelease(tag.Name)) + .ToList(); + + if (tags.Count == 0) + { + return null; + } + + if (tags.Count > 1) + { + var message = string.Format("Commit '{0}' bears more than one stable tag: {1}", c.Id.ToString(7), string.Join(", ", tags.Select(t => t.Name))); + throw new WarningException(message); + } + + var stableTag = tags.Single(); + var commit = RetrieveMergeCommit(stableTag); + + return commit; + } + + static bool IsStableRelease(string tagName) + { + ShortVersion shortVersion; + return ShortVersionParser.TryParseMajorMinor(tagName, out shortVersion); + } + + static Commit RetrieveMergeCommit(Tag stableTag) + { + var target = stableTag.PeeledTarget(); + var commit = target as Commit; + if (commit != null) + { + return commit; + } + var message = string.Format("Target '{0}' of Tag '{1}' isn't a Commit.", target.Id.ToString(7), stableTag.Name); + throw new WarningException(message); + } + + + } +} \ No newline at end of file diff --git a/GitVersionCore/LibGitExtensions.cs b/GitVersionCore/LibGitExtensions.cs index 2ffe323ca7..e1621e7214 100644 --- a/GitVersionCore/LibGitExtensions.cs +++ b/GitVersionCore/LibGitExtensions.cs @@ -24,20 +24,6 @@ public static Branch FindBranch(this IRepository repository, string branchName) return repository.Branches.FirstOrDefault(x => x.Name == "origin/" + branchName); } - public static SemanticVersion NewestSemVerTag(this IRepository repository, Commit commit) - { - foreach (var tag in repository.TagsByDate(commit)) - { - SemanticVersion version; - if (SemanticVersion.TryParse(tag.Name, out version)) - { - return version; - } - } - - return null; - } - public static IEnumerable TagsByDate(this IRepository repository, Commit commit) { return repository.Tags @@ -75,17 +61,12 @@ public static bool IsDetachedHead(this Branch branch) return branch.CanonicalName.Equals("(no branch)", StringComparison.OrdinalIgnoreCase); } - public static string GetRepositoryDirectory(this IRepository repository) + public static string GetRepositoryDirectory(this IRepository repository, bool omitGitPostFix = true) { - var gitDirectory = repository.Info.Path; + var gitDirectory = omitGitPostFix ? repository.Info.WorkingDirectory : repository.Info.Path; gitDirectory = gitDirectory.TrimEnd('\\'); - if (gitDirectory.EndsWith(".git")) - { - gitDirectory = gitDirectory.Substring(0, gitDirectory.Length - ".git".Length); - } - return gitDirectory; } diff --git a/GitVersionCore/OutputVariables/VariableProvider.cs b/GitVersionCore/OutputVariables/VariableProvider.cs index 2099a941fc..2cdf76f49d 100644 --- a/GitVersionCore/OutputVariables/VariableProvider.cs +++ b/GitVersionCore/OutputVariables/VariableProvider.cs @@ -58,9 +58,6 @@ public static Dictionary GetVariablesFor( semanticVersion.PreReleaseTag.HasTag() ? "-" + semanticVersion.PreReleaseTag : null)}, {BranchName, bmd.Branch}, {Sha, bmd.Sha}, - {OriginalRelease, string.Format("{0}.{1}", - bmd.ReleaseDate.OriginalCommitSha, - bmd.ReleaseDate.OriginalDate.UtcDateTime.ToString("u"))}, }; // Use ToLower() to fix a bug where Beta and beta are different in NuGet diff --git a/GitVersionCore/ReleaseDate.cs b/GitVersionCore/ReleaseDate.cs deleted file mode 100644 index ffb77b6296..0000000000 --- a/GitVersionCore/ReleaseDate.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using GitVersion; - -public class ReleaseDate : IEquatable -{ - public DateTimeOffset OriginalDate; - public string OriginalCommitSha; - public DateTimeOffset Date; - public string CommitSha; - - static LambdaEqualityHelper equalityHelper = - new LambdaEqualityHelper(x => x.OriginalDate, x => x.OriginalCommitSha, x => x.Date, x => x.CommitSha); - - public override bool Equals(object obj) - { - return Equals(obj as ReleaseDate); - } - - public bool Equals(ReleaseDate other) - { - return equalityHelper.Equals(this, other); - } - - public override int GetHashCode() - { - return equalityHelper.GetHashCode(this); - } - - public static bool operator ==(ReleaseDate left, ReleaseDate right) - { - return Equals(left, right); - } - - public static bool operator !=(ReleaseDate left, ReleaseDate right) - { - return !Equals(left, right); - } -} diff --git a/GitVersionCore/ReleaseDateFinder.cs b/GitVersionCore/ReleaseDateFinder.cs deleted file mode 100644 index d8cde64334..0000000000 --- a/GitVersionCore/ReleaseDateFinder.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System.Diagnostics; -using GitVersion; -using LibGit2Sharp; - -public class ReleaseDateFinder -{ - public static ReleaseDate Execute(IRepository repo, string commitSha, int calculatedPatch) - { - var c = repo.Lookup(commitSha); - Debug.Assert(c != null); - - var rd = new ReleaseDate - { - OriginalDate = c.When(), - OriginalCommitSha = c.Sha, - Date = c.When(), - CommitSha = c.Sha, - }; - - if (GitVersionFinder.ShouldGitHubFlowVersioningSchemeApply(repo)) - { - return rd; - } - - if (calculatedPatch == 0) - { - return rd; - } - - var vp = new VersionOnMasterFinder().FindLatestStableTaggedCommitReachableFrom(repo, c); - var latestStable = repo.Lookup(vp.CommitSha); - Debug.Assert(latestStable != null); - - rd.OriginalDate = latestStable.When(); - rd.OriginalCommitSha = vp.CommitSha; - return rd; - } -} diff --git a/GitVersionCore/RepositoryLoader.cs b/GitVersionCore/RepositoryLoader.cs index 8b3dfafcdd..41e0dfece2 100644 --- a/GitVersionCore/RepositoryLoader.cs +++ b/GitVersionCore/RepositoryLoader.cs @@ -9,7 +9,14 @@ public static Repository GetRepo(string gitDirectory) { try { - return new Repository(gitDirectory); + var repository = new Repository(gitDirectory); + + var branch = repository.Head; + if (branch.Tip == null) + { + throw new WarningException("No Tip found. Has repo been initialized?"); + } + return repository; } catch (Exception exception) { diff --git a/GitVersionCore/SemanticVersionBuildMetaData.cs b/GitVersionCore/SemanticVersionBuildMetaData.cs index d032427225..b3db9d8e2a 100644 --- a/GitVersionCore/SemanticVersionBuildMetaData.cs +++ b/GitVersionCore/SemanticVersionBuildMetaData.cs @@ -10,27 +10,27 @@ public class SemanticVersionBuildMetaData : IFormattable, IEquatable equalityHelper = - new LambdaEqualityHelper(x => x.CommitsSinceTag, x => x.Branch, x => x.Sha, x => x.ReleaseDate); + new LambdaEqualityHelper(x => x.CommitsSinceTag, x => x.Branch, x => x.Sha); public int? CommitsSinceTag; public string Branch; - public ReleaseDate ReleaseDate; public string Sha; public string OtherMetaData; + public DateTimeOffset CommitDate; public SemanticVersionBuildMetaData() { } - public SemanticVersionBuildMetaData( - int? commitsSinceTag, string branch, ReleaseDate releaseDate) + public SemanticVersionBuildMetaData(int? commitsSinceTag, string branch, string commitSha,DateTimeOffset commitDate) { - ReleaseDate = releaseDate; - Sha = releaseDate.CommitSha; + Sha = commitSha; CommitsSinceTag = commitsSinceTag; Branch = branch; + CommitDate = commitDate; } + public override bool Equals(object obj) { return Equals(obj as SemanticVersionBuildMetaData); diff --git a/GitVersionCore/SemanticVersionExtensions.cs b/GitVersionCore/SemanticVersionExtensions.cs index 002ffddfbb..ce12ab3e88 100644 --- a/GitVersionCore/SemanticVersionExtensions.cs +++ b/GitVersionCore/SemanticVersionExtensions.cs @@ -7,8 +7,8 @@ public static class SemanticVersionExtensions public static void OverrideVersionManuallyIfNeeded(this SemanticVersion version, IRepository repository) { var nextVersionTxtFileFinder = new NextVersionTxtFileFinder(repository.GetRepositoryDirectory()); - var manualNextVersion = nextVersionTxtFileFinder.GetNextVersion(); - if (!manualNextVersion.IsEmpty()) + SemanticVersion manualNextVersion ; + if (nextVersionTxtFileFinder.TryGetNextVersion(out manualNextVersion)) { if (manualNextVersion > version) { diff --git a/GitVersionCore/ShortVersionParser.cs b/GitVersionCore/ShortVersionParser.cs index 921309229d..a8cb098cc1 100644 --- a/GitVersionCore/ShortVersionParser.cs +++ b/GitVersionCore/ShortVersionParser.cs @@ -4,12 +4,14 @@ namespace GitVersion class ShortVersionParser { - public static void Parse(string versionString, out ShortVersion shortVersion) + public static ShortVersion Parse(string versionString) { + ShortVersion shortVersion; if (!TryParse(versionString, out shortVersion)) { throw new Exception(string.Format("Could not parse version from '{0}' expected 'major.minor.patch'", versionString)); } + return shortVersion; } public static bool TryParseMajorMinor(string versionString, out ShortVersion shortVersion) @@ -25,8 +27,8 @@ public static bool TryParseMajorMinor(string versionString, out ShortVersion sho public static bool TryParse(string versionString, out ShortVersion shortVersion) { - var major = 0; - var minor = 0; + int major; + int minor; var patch = 0; var strings = versionString.Split('.'); if (strings.Length < 2 || strings.Length > 3) diff --git a/GitVersionCore/VersionCache.cs b/GitVersionCore/VersionCache.cs deleted file mode 100644 index 44be88874a..0000000000 --- a/GitVersionCore/VersionCache.cs +++ /dev/null @@ -1,61 +0,0 @@ -namespace GitVersion -{ - using System.Collections.Generic; - using LibGit2Sharp; - - public static class VersionCache - { - static Dictionary versionCacheVersions = new Dictionary(); - - public static SemanticVersion GetVersion(string gitDirectory) - { - using (var repo = RepositoryLoader.GetRepo(gitDirectory)) - { - var branch = repo.Head; - if (branch.Tip == null) - { - throw new WarningException("No Tip found. Has repo been initialized?"); - } - - var ticks = DirectoryDateFinder.GetLastDirectoryWrite(gitDirectory); - var key = string.Format("{0}:{1}:{2}", repo.Head.CanonicalName, repo.Head.Tip.Sha, ticks); - CachedVersion cachedVersion; - SemanticVersion versionAndBranch; - if (versionCacheVersions.TryGetValue(key, out cachedVersion)) - { - Logger.WriteInfo("Version read from cache."); - if (cachedVersion.Timestamp == ticks) - { - versionAndBranch = cachedVersion.SemanticVersion; - } - else - { - Logger.WriteInfo("Change detected. flushing cache."); - versionAndBranch = cachedVersion.SemanticVersion = GetSemanticVersion(repo); - } - } - else - { - Logger.WriteInfo("Version not in cache. Calculating version."); - versionAndBranch = GetSemanticVersion(repo); - - versionCacheVersions[key] = new CachedVersion - { - SemanticVersion = versionAndBranch, - Timestamp = ticks - }; - } - - return versionAndBranch; - } - } - - static SemanticVersion GetSemanticVersion(Repository repository) - { - var versionForRepositoryFinder = new GitVersionFinder(); - var gitVersionContext = new GitVersionContext(repository); - Logger.WriteInfo("Running against branch: " + gitVersionContext.CurrentBranch.Name); - return versionForRepositoryFinder.FindVersion(gitVersionContext); - } - } -} \ No newline at end of file diff --git a/GitVersionCore/VersionOnMasterFinder.cs b/GitVersionCore/VersionOnMasterFinder.cs deleted file mode 100644 index 1a0fe17d01..0000000000 --- a/GitVersionCore/VersionOnMasterFinder.cs +++ /dev/null @@ -1,138 +0,0 @@ -namespace GitVersion -{ - using System; - using System.Collections.Generic; - using System.Diagnostics; - using System.Linq; - using LibGit2Sharp; - - class VersionOnMasterFinder - { - public VersionPoint Execute(GitVersionContext context, DateTimeOffset olderThan) - { - var masterBranch = context.Repository.FindBranch("master"); - foreach (var commit in masterBranch.CommitsPriorToThan(olderThan)) - { - foreach (var tag in context.Repository.TagsByDate(commit)) - { - ShortVersion shortVersion; - if (ShortVersionParser.TryParseMajorMinor(tag.Name, out shortVersion)) - { - return new VersionPoint - { - Major = shortVersion.Major, - Minor = shortVersion.Minor, - Timestamp = commit.When(), - CommitSha = commit.Sha, - }; - } - } - - ShortVersion shortVersionFromMergeMessage; - if (MergeMessageParser.TryParse(commit, out shortVersionFromMergeMessage)) - { - return new VersionPoint - { - Major = shortVersionFromMergeMessage.Major, - Minor = shortVersionFromMergeMessage.Minor, - Timestamp = commit.When(), - CommitSha = commit.Sha, - }; - } - } - return new VersionPoint - { - Major = 0, - Minor = 1, - Timestamp = DateTimeOffset.MinValue, - CommitSha = null, - }; - } - - public VersionPoint FindLatestStableTaggedCommitReachableFrom(IRepository repo, Commit commit) - { - var masterTip = repo.FindBranch("master").Tip; - var ancestor = repo.Commits.FindMergeBase(masterTip, commit); - - var allTags = repo.Tags.ToList(); - - foreach (var c in repo.Commits.QueryBy(new CommitFilter - { - Since = ancestor.Id, - SortBy = CommitSortStrategies.Topological | CommitSortStrategies.Time - } - )) - { - var vp = RetrieveStableVersionPointFor(allTags, c); - - if (vp != null) - { - return vp; - } - } - - return null; - } - - static VersionPoint RetrieveStableVersionPointFor(IEnumerable allTags, Commit c) - { - var tags = allTags - .Where(tag => tag.PeeledTarget() == c) - .Where(tag => IsStableRelease(tag.Name)) - .ToList(); - - if (tags.Count == 0) - { - return null; - } - - if (tags.Count > 1) - { - throw new WarningException( - string.Format("Commit '{0}' bears more than one stable tag: {1}", - c.Id.ToString(7), string.Join(", ", tags.Select(t => t.Name)))); - } - - var stableTag = tags.Single(); - var commit = RetrieveMergeCommit(stableTag); - - return BuildFrom(stableTag, commit); - } - - static VersionPoint BuildFrom(Tag stableTag, Commit commit) - { - ShortVersion shortVersion; - - var hasParsed = ShortVersionParser.TryParseMajorMinor(stableTag.Name, out shortVersion); - Debug.Assert(hasParsed); - - return new VersionPoint - { - Major = shortVersion.Major, - Minor = shortVersion.Minor, - CommitSha = commit.Id.Sha, - }; - } - - static Commit RetrieveMergeCommit(Tag stableTag) - { - var target = stableTag.PeeledTarget(); - if (!(target is Commit)) - { - throw new WarningException( - string.Format("Target '{0}' of Tag '{1}' isn't a Commit.", - target.Id.ToString(7), stableTag.Name)); - } - - var targetCommit = (Commit) target; - - return targetCommit; - } - - static bool IsStableRelease(string tagName) - { - ShortVersion shortVersion; - return ShortVersionParser.TryParseMajorMinor(tagName, out shortVersion); - } - } -} diff --git a/GitVersionCore/VersionPoint.cs b/GitVersionCore/VersionPoint.cs index 6c23e38218..99924273bd 100644 --- a/GitVersionCore/VersionPoint.cs +++ b/GitVersionCore/VersionPoint.cs @@ -1,12 +1,8 @@ namespace GitVersion { - using System; - class VersionPoint { public int Major; public int Minor; - public DateTimeOffset Timestamp; - public string CommitSha; } } diff --git a/GitVersionExe/Program.cs b/GitVersionExe/Program.cs index 52f861e4c0..b49e3073e2 100644 --- a/GitVersionExe/Program.cs +++ b/GitVersionExe/Program.cs @@ -59,8 +59,11 @@ static void Main() { buildServer.PerformPreProcessingSteps(gitDirectory); } - - var semanticVersion = VersionCache.GetVersion(gitDirectory); + SemanticVersion semanticVersion; + using (var repo = RepositoryLoader.GetRepo(gitDirectory)) + { + semanticVersion = GitVersionFinder.GetSemanticVersion(repo); + } if (arguments.Output == OutputType.BuildServer) { diff --git a/GitVersionTask.Tests/AssemblyInfoBuilderTests.VerifyAssemblyVersion_Major.approved.txt b/GitVersionTask.Tests/AssemblyInfoBuilderTests.VerifyAssemblyVersion_Major.approved.txt index 86464b7651..240b386c5c 100644 --- a/GitVersionTask.Tests/AssemblyInfoBuilderTests.VerifyAssemblyVersion_Major.approved.txt +++ b/GitVersionTask.Tests/AssemblyInfoBuilderTests.VerifyAssemblyVersion_Major.approved.txt @@ -41,7 +41,6 @@ static class GitVersionInformation public static string ClassicVersionWithTag = "2.3.4.5"; public static string BranchName = "master"; public static string Sha = "commitSha"; - public static string OriginalRelease = "originalCommitSha.2014-03-01 00:00:01Z"; public static string NuGetVersionV2 = "2.3.4"; public static string NuGetVersion = "2.3.4"; diff --git a/GitVersionTask.Tests/AssemblyInfoBuilderTests.VerifyAssemblyVersion_MajorMinor.approved.txt b/GitVersionTask.Tests/AssemblyInfoBuilderTests.VerifyAssemblyVersion_MajorMinor.approved.txt index 525dc01d60..d2be3bebb2 100644 --- a/GitVersionTask.Tests/AssemblyInfoBuilderTests.VerifyAssemblyVersion_MajorMinor.approved.txt +++ b/GitVersionTask.Tests/AssemblyInfoBuilderTests.VerifyAssemblyVersion_MajorMinor.approved.txt @@ -41,7 +41,6 @@ static class GitVersionInformation public static string ClassicVersionWithTag = "2.3.4.5"; public static string BranchName = "master"; public static string Sha = "commitSha"; - public static string OriginalRelease = "originalCommitSha.2014-03-01 00:00:01Z"; public static string NuGetVersionV2 = "2.3.4"; public static string NuGetVersion = "2.3.4"; diff --git a/GitVersionTask.Tests/AssemblyInfoBuilderTests.VerifyAssemblyVersion_MajorMinorPatch.approved.txt b/GitVersionTask.Tests/AssemblyInfoBuilderTests.VerifyAssemblyVersion_MajorMinorPatch.approved.txt index 98b390090d..2992714dad 100644 --- a/GitVersionTask.Tests/AssemblyInfoBuilderTests.VerifyAssemblyVersion_MajorMinorPatch.approved.txt +++ b/GitVersionTask.Tests/AssemblyInfoBuilderTests.VerifyAssemblyVersion_MajorMinorPatch.approved.txt @@ -41,7 +41,6 @@ static class GitVersionInformation public static string ClassicVersionWithTag = "2.3.4.5"; public static string BranchName = "master"; public static string Sha = "commitSha"; - public static string OriginalRelease = "originalCommitSha.2014-03-01 00:00:01Z"; public static string NuGetVersionV2 = "2.3.4"; public static string NuGetVersion = "2.3.4"; diff --git a/GitVersionTask.Tests/AssemblyInfoBuilderTests.VerifyCreatedCode.approved.txt b/GitVersionTask.Tests/AssemblyInfoBuilderTests.VerifyCreatedCode.approved.txt index e038cd8ee8..f3e042aeac 100644 --- a/GitVersionTask.Tests/AssemblyInfoBuilderTests.VerifyCreatedCode.approved.txt +++ b/GitVersionTask.Tests/AssemblyInfoBuilderTests.VerifyCreatedCode.approved.txt @@ -41,7 +41,6 @@ static class GitVersionInformation public static string ClassicVersionWithTag = "1.2.3.5-unstable.4"; public static string BranchName = "feature1"; public static string Sha = "commitSha"; - public static string OriginalRelease = "originalCommitSha.2014-03-01 00:00:01Z"; public static string NuGetVersionV2 = "1.2.3-unstable0004"; public static string NuGetVersion = "1.2.3-unstable0004"; diff --git a/GitVersionTask.Tests/AssemblyInfoBuilderTests.cs b/GitVersionTask.Tests/AssemblyInfoBuilderTests.cs index a603a136e4..167c3013c3 100644 --- a/GitVersionTask.Tests/AssemblyInfoBuilderTests.cs +++ b/GitVersionTask.Tests/AssemblyInfoBuilderTests.cs @@ -22,23 +22,20 @@ public void VerifyCreatedCode() Patch = 3, PreReleaseTag = "unstable4", BuildMetaData = new SemanticVersionBuildMetaData(5, - "feature1", - new ReleaseDate - { - OriginalCommitSha = "originalCommitSha", - OriginalDate = DateTimeOffset.Parse("2014-03-01 00:00:01Z"), - CommitSha = "commitSha", - Date = DateTimeOffset.Parse("2014-03-06 23:59:59Z") - }) + "feature1", "commitSha", DateTimeOffset.Parse("2014-03-06 23:59:59Z")) }; var assemblyInfoBuilder = new AssemblyInfoBuilder + { + CachedVersion = new CachedVersion { - SemanticVersion = semanticVersion - }; + SemanticVersion = semanticVersion, + MasterReleaseDate = DateTimeOffset.Parse("2014-03-01 00:00:01Z"), + } + }; var assemblyInfoText = assemblyInfoBuilder.GetAssemblyInfoText(); Approvals.Verify(assemblyInfoText); var syntaxTree = SyntaxTree.ParseText(assemblyInfoText); - var references = new[] {new MetadataFileReference(typeof(object).Assembly.Location), }; + var references = new[] { new MetadataFileReference(typeof(object).Assembly.Location) }; var compilation = Compilation.Create("Greeter.dll", new CompilationOptions(OutputKind.NetModule), new[] { syntaxTree }, references); var emitResult = compilation.Emit(new MemoryStream()); Assert.IsTrue(emitResult.Success, string.Join(Environment.NewLine, emitResult.Diagnostics.Select(x => x.Info))); @@ -73,25 +70,22 @@ static void VerifyAssemblyVersion(AssemblyVersioningScheme avs) Minor = 3, Patch = 4, BuildMetaData = new SemanticVersionBuildMetaData(5, - "master", - new ReleaseDate - { - OriginalCommitSha = "originalCommitSha", - OriginalDate = DateTimeOffset.Parse("2014-03-01 00:00:01Z"), - CommitSha = "commitSha", - Date = DateTimeOffset.Parse("2014-03-06 23:59:59Z") - }), + "master", "commitSha", DateTimeOffset.Parse("2014-03-06 23:59:59Z")), }; var assemblyInfoBuilder = new AssemblyInfoBuilder { - SemanticVersion = semanticVersion, + CachedVersion = new CachedVersion + { + SemanticVersion = semanticVersion, + MasterReleaseDate = DateTimeOffset.Parse("2014-03-01 00:00:01Z") + }, AssemblyVersioningScheme = avs, }; var assemblyInfoText = assemblyInfoBuilder.GetAssemblyInfoText(); Approvals.Verify(assemblyInfoText); var syntaxTree = SyntaxTree.ParseText(assemblyInfoText); - var references = new[] { new MetadataFileReference(typeof(object).Assembly.Location), }; + var references = new[] { new MetadataFileReference(typeof(object).Assembly.Location) }; var compilation = Compilation.Create("Greeter.dll", new CompilationOptions(OutputKind.NetModule), new[] { syntaxTree }, references); var emitResult = compilation.Emit(new MemoryStream()); Assert.IsTrue(emitResult.Success, string.Join(Environment.NewLine, emitResult.Diagnostics.Select(x => x.Info))); diff --git a/GitVersionTask.Tests/BranchFinders/FeatureBranchTests.Feature_branch_with_1_commit.approved.txt b/GitVersionTask.Tests/BranchFinders/FeatureBranchTests.Feature_branch_with_1_commit.approved.txt index 43d1fa61bf..8f81073aa6 100644 --- a/GitVersionTask.Tests/BranchFinders/FeatureBranchTests.Feature_branch_with_1_commit.approved.txt +++ b/GitVersionTask.Tests/BranchFinders/FeatureBranchTests.Feature_branch_with_1_commit.approved.txt @@ -9,13 +9,8 @@ "BuildMetaData": { "CommitsSinceTag": 1, "Branch": "featureWithOneCommit", - "ReleaseDate": { - "OriginalDate": "", - "OriginalCommitSha": "000000000000000000000000000000000000000", - "Date": "", - "CommitSha": "000000000000000000000000000000000000000" - }, "Sha": "000000000000000000000000000000000000000", - "OtherMetaData": null + "OtherMetaData": null, + "CommitDate": "" } } \ No newline at end of file diff --git a/GitVersionTask.Tests/BranchFinders/FeatureBranchTests.Feature_branch_with_2_commits.approved.txt b/GitVersionTask.Tests/BranchFinders/FeatureBranchTests.Feature_branch_with_2_commits.approved.txt index aa5e4237d4..8dd2f6d0fa 100644 --- a/GitVersionTask.Tests/BranchFinders/FeatureBranchTests.Feature_branch_with_2_commits.approved.txt +++ b/GitVersionTask.Tests/BranchFinders/FeatureBranchTests.Feature_branch_with_2_commits.approved.txt @@ -9,13 +9,8 @@ "BuildMetaData": { "CommitsSinceTag": 2, "Branch": "featureWithOneCommit", - "ReleaseDate": { - "OriginalDate": "", - "OriginalCommitSha": "000000000000000000000000000000000000000", - "Date": "", - "CommitSha": "000000000000000000000000000000000000000" - }, "Sha": "000000000000000000000000000000000000000", - "OtherMetaData": null + "OtherMetaData": null, + "CommitDate": "" } } \ No newline at end of file diff --git a/GitVersionTask.Tests/BranchFinders/FeatureBranchTests.Feature_branch_with_2_commits_but_building_an_commit.approved.txt b/GitVersionTask.Tests/BranchFinders/FeatureBranchTests.Feature_branch_with_2_commits_but_building_an_commit.approved.txt index aa5e4237d4..8dd2f6d0fa 100644 --- a/GitVersionTask.Tests/BranchFinders/FeatureBranchTests.Feature_branch_with_2_commits_but_building_an_commit.approved.txt +++ b/GitVersionTask.Tests/BranchFinders/FeatureBranchTests.Feature_branch_with_2_commits_but_building_an_commit.approved.txt @@ -9,13 +9,8 @@ "BuildMetaData": { "CommitsSinceTag": 2, "Branch": "featureWithOneCommit", - "ReleaseDate": { - "OriginalDate": "", - "OriginalCommitSha": "000000000000000000000000000000000000000", - "Date": "", - "CommitSha": "000000000000000000000000000000000000000" - }, "Sha": "000000000000000000000000000000000000000", - "OtherMetaData": null + "OtherMetaData": null, + "CommitDate": "" } } \ No newline at end of file diff --git a/GitVersionTask.Tests/BranchFinders/MasterTests.Hotfix_merge.approved.txt b/GitVersionTask.Tests/BranchFinders/MasterTests.Hotfix_merge.approved.txt index f2d129e098..93c9c3f1e5 100644 --- a/GitVersionTask.Tests/BranchFinders/MasterTests.Hotfix_merge.approved.txt +++ b/GitVersionTask.Tests/BranchFinders/MasterTests.Hotfix_merge.approved.txt @@ -9,13 +9,8 @@ "BuildMetaData": { "CommitsSinceTag": null, "Branch": "master", - "ReleaseDate": { - "OriginalDate": "", - "OriginalCommitSha": "000000000000000000000000000000000000000", - "Date": "", - "CommitSha": "000000000000000000000000000000000000000" - }, "Sha": "000000000000000000000000000000000000000", - "OtherMetaData": null + "OtherMetaData": null, + "CommitDate": "" } } \ No newline at end of file diff --git a/GitVersionTask.Tests/BranchFinders/MasterTests.Override_using_tag_with_a_stable_release.approved.txt b/GitVersionTask.Tests/BranchFinders/MasterTests.Override_using_tag_with_a_stable_release.approved.txt index f245ece079..9826785aac 100644 --- a/GitVersionTask.Tests/BranchFinders/MasterTests.Override_using_tag_with_a_stable_release.approved.txt +++ b/GitVersionTask.Tests/BranchFinders/MasterTests.Override_using_tag_with_a_stable_release.approved.txt @@ -9,13 +9,8 @@ "BuildMetaData": { "CommitsSinceTag": null, "Branch": "master", - "ReleaseDate": { - "OriginalDate": "", - "OriginalCommitSha": "000000000000000000000000000000000000000", - "Date": "", - "CommitSha": "000000000000000000000000000000000000000" - }, "Sha": "000000000000000000000000000000000000000", - "OtherMetaData": null + "OtherMetaData": null, + "CommitDate": "" } } \ No newline at end of file diff --git a/GitVersionTask.Tests/BranchFinders/MasterTests.Release_merge.approved.txt b/GitVersionTask.Tests/BranchFinders/MasterTests.Release_merge.approved.txt index f245ece079..9826785aac 100644 --- a/GitVersionTask.Tests/BranchFinders/MasterTests.Release_merge.approved.txt +++ b/GitVersionTask.Tests/BranchFinders/MasterTests.Release_merge.approved.txt @@ -9,13 +9,8 @@ "BuildMetaData": { "CommitsSinceTag": null, "Branch": "master", - "ReleaseDate": { - "OriginalDate": "", - "OriginalCommitSha": "000000000000000000000000000000000000000", - "Date": "", - "CommitSha": "000000000000000000000000000000000000000" - }, "Sha": "000000000000000000000000000000000000000", - "OtherMetaData": null + "OtherMetaData": null, + "CommitDate": "" } } \ No newline at end of file diff --git a/GitVersionTask.Tests/BranchFinders/PullBranchTests.Pull_branch_with_1_commit.approved.txt b/GitVersionTask.Tests/BranchFinders/PullBranchTests.Pull_branch_with_1_commit.approved.txt index df721000df..aeeb7076a6 100644 --- a/GitVersionTask.Tests/BranchFinders/PullBranchTests.Pull_branch_with_1_commit.approved.txt +++ b/GitVersionTask.Tests/BranchFinders/PullBranchTests.Pull_branch_with_1_commit.approved.txt @@ -9,13 +9,8 @@ "BuildMetaData": { "CommitsSinceTag": 1, "Branch": "pull/1735/merge", - "ReleaseDate": { - "OriginalDate": "", - "OriginalCommitSha": "000000000000000000000000000000000000000", - "Date": "", - "CommitSha": "000000000000000000000000000000000000000" - }, "Sha": "000000000000000000000000000000000000000", - "OtherMetaData": null + "OtherMetaData": null, + "CommitDate": "" } } \ No newline at end of file diff --git a/GitVersionTask.Tests/BranchFinders/PullBranchTests.Pull_branch_with_2_commits.approved.txt b/GitVersionTask.Tests/BranchFinders/PullBranchTests.Pull_branch_with_2_commits.approved.txt index c174208438..a4909a65d4 100644 --- a/GitVersionTask.Tests/BranchFinders/PullBranchTests.Pull_branch_with_2_commits.approved.txt +++ b/GitVersionTask.Tests/BranchFinders/PullBranchTests.Pull_branch_with_2_commits.approved.txt @@ -9,13 +9,8 @@ "BuildMetaData": { "CommitsSinceTag": 2, "Branch": "pull/1735/merge", - "ReleaseDate": { - "OriginalDate": "", - "OriginalCommitSha": "000000000000000000000000000000000000000", - "Date": "", - "CommitSha": "000000000000000000000000000000000000000" - }, "Sha": "000000000000000000000000000000000000000", - "OtherMetaData": null + "OtherMetaData": null, + "CommitDate": "" } } \ No newline at end of file diff --git a/GitVersionTask.Tests/BranchFinders/ReleaseTests.Tag_on_commit_should_be_exact_tag.approved.txt b/GitVersionTask.Tests/BranchFinders/ReleaseTests.Tag_on_commit_should_be_exact_tag.approved.txt index 94332dd962..089ae71ab9 100644 --- a/GitVersionTask.Tests/BranchFinders/ReleaseTests.Tag_on_commit_should_be_exact_tag.approved.txt +++ b/GitVersionTask.Tests/BranchFinders/ReleaseTests.Tag_on_commit_should_be_exact_tag.approved.txt @@ -9,13 +9,8 @@ "BuildMetaData": { "CommitsSinceTag": 1, "Branch": "release-5.0.0", - "ReleaseDate": { - "OriginalDate": "", - "OriginalCommitSha": "000000000000000000000000000000000000000", - "Date": "", - "CommitSha": "000000000000000000000000000000000000000" - }, "Sha": "000000000000000000000000000000000000000", - "OtherMetaData": null + "OtherMetaData": null, + "CommitDate": "" } } \ No newline at end of file diff --git a/GitVersionTask.Tests/BranchFinders/ReleaseTests.cs b/GitVersionTask.Tests/BranchFinders/ReleaseTests.cs index 037c1eca14..3bf3d6e506 100644 --- a/GitVersionTask.Tests/BranchFinders/ReleaseTests.cs +++ b/GitVersionTask.Tests/BranchFinders/ReleaseTests.cs @@ -1,3 +1,4 @@ +using System; using GitVersion; using LibGit2Sharp; using NUnit.Framework; @@ -36,7 +37,7 @@ public void EnsureAReleaseBranchNameDoesNotExposeAStability() var finder = new ReleaseVersionFinder(); - Assert.Throws(() => finder.FindVersion(new GitVersionContext(repo, releaseBranch))); + Assert.Throws(() => finder.FindVersion(new GitVersionContext(repo, releaseBranch))); } } diff --git a/GitVersionTask.Tests/BuildServers/BuildServerBaseTests.cs b/GitVersionTask.Tests/BuildServers/BuildServerBaseTests.cs index dcb09d24c5..2582c199f8 100644 --- a/GitVersionTask.Tests/BuildServers/BuildServerBaseTests.cs +++ b/GitVersionTask.Tests/BuildServers/BuildServerBaseTests.cs @@ -20,15 +20,8 @@ public void BuildNumberIsFullSemVer() BuildMetaData = "5" }; - semanticVersion.BuildMetaData.ReleaseDate = new ReleaseDate - { - OriginalCommitSha = "originalCommitSha", - OriginalDate = DateTimeOffset.Parse("2014-03-01 00:00:01Z"), - CommitSha = "commitSha", - Date = DateTimeOffset.Parse("2014-03-06 23:59:59Z") - }; - - + semanticVersion.BuildMetaData.CommitDate = DateTimeOffset.Parse("2014-03-06 23:59:59Z"); + semanticVersion.BuildMetaData.Sha = "commitSha"; new BuildServer().WriteIntegration(semanticVersion, writes.Add); writes[1].ShouldBe("1.2.3-beta.1+5"); diff --git a/GitVersionTask.Tests/GetVersionTaskTests.cs b/GitVersionTask.Tests/GetVersionTaskTests.cs index 61098aa24a..2747f1b53a 100644 --- a/GitVersionTask.Tests/GetVersionTaskTests.cs +++ b/GitVersionTask.Tests/GetVersionTaskTests.cs @@ -20,13 +20,7 @@ public void OutputsShouldMatchVariableProvider() Major = 1, Minor = 2, Patch = 3, - BuildMetaData = new SemanticVersionBuildMetaData(5, "develop", new ReleaseDate - { - OriginalCommitSha = "originalCommitSha", - OriginalDate = DateTimeOffset.Parse("2014-03-01 00:00:01Z"), - CommitSha = "commitSha", - Date = DateTimeOffset.Parse("2014-03-06 23:59:59Z") - }) + BuildMetaData = new SemanticVersionBuildMetaData(5, "develop", "commitSha",DateTimeOffset.Parse("2014-03-06 23:59:59Z")) }).Keys; CollectionAssert.AreEquivalent(properties, variables); diff --git a/GitVersionTask.Tests/GitFlow/GitVersionFinderTests.AFeatureBranchDoesNotRequireASpecificPrefix.approved.txt b/GitVersionTask.Tests/GitFlow/GitVersionFinderTests.AFeatureBranchDoesNotRequireASpecificPrefix.approved.txt index 10f0dcc6f6..838ceacca0 100644 --- a/GitVersionTask.Tests/GitFlow/GitVersionFinderTests.AFeatureBranchDoesNotRequireASpecificPrefix.approved.txt +++ b/GitVersionTask.Tests/GitFlow/GitVersionFinderTests.AFeatureBranchDoesNotRequireASpecificPrefix.approved.txt @@ -9,13 +9,8 @@ "BuildMetaData": { "CommitsSinceTag": 1, "Branch": "every-feature-is-welcome", - "ReleaseDate": { - "OriginalDate": "", - "OriginalCommitSha": "000000000000000000000000000000000000000", - "Date": "", - "CommitSha": "000000000000000000000000000000000000000" - }, "Sha": "000000000000000000000000000000000000000", - "OtherMetaData": null + "OtherMetaData": null, + "CommitDate": "" } } \ No newline at end of file diff --git a/GitVersionTask.Tests/GitFlow/GitVersionFinderTests.AFeatureBranchPrefixIsNotIncludedInTag.approved.txt b/GitVersionTask.Tests/GitFlow/GitVersionFinderTests.AFeatureBranchPrefixIsNotIncludedInTag.approved.txt index 27307b4e4a..a7a459f70c 100644 --- a/GitVersionTask.Tests/GitFlow/GitVersionFinderTests.AFeatureBranchPrefixIsNotIncludedInTag.approved.txt +++ b/GitVersionTask.Tests/GitFlow/GitVersionFinderTests.AFeatureBranchPrefixIsNotIncludedInTag.approved.txt @@ -9,13 +9,8 @@ "BuildMetaData": { "CommitsSinceTag": 1, "Branch": "feature/ABC-1234_SomeDescription", - "ReleaseDate": { - "OriginalDate": "", - "OriginalCommitSha": "000000000000000000000000000000000000000", - "Date": "", - "CommitSha": "000000000000000000000000000000000000000" - }, "Sha": "000000000000000000000000000000000000000", - "OtherMetaData": null + "OtherMetaData": null, + "CommitDate": "" } } \ No newline at end of file diff --git a/GitVersionTask.Tests/GitHubFlow/MergedBranchesWithVersionFinderTests.cs b/GitVersionTask.Tests/GitHubFlow/MergedBranchesWithVersionFinderTests.cs index 02efd7a4a2..976d8b6af9 100644 --- a/GitVersionTask.Tests/GitHubFlow/MergedBranchesWithVersionFinderTests.cs +++ b/GitVersionTask.Tests/GitHubFlow/MergedBranchesWithVersionFinderTests.cs @@ -18,7 +18,8 @@ public void ShouldFindMergeCommit() }; var sut = new MergedBranchesWithVersionFinder(new GitVersionContext(null, currentBranch)); - var version = sut.GetVersion(); + SemanticVersion version; + sut.TryGetVersion(out version); version.ToString().ShouldBe("2.0.0"); } diff --git a/GitVersionTask.Tests/LibGitExtensionsTests.cs b/GitVersionTask.Tests/LibGitExtensionsTests.cs index 1a2d9a59c7..8f881f40de 100644 --- a/GitVersionTask.Tests/LibGitExtensionsTests.cs +++ b/GitVersionTask.Tests/LibGitExtensionsTests.cs @@ -1,4 +1,3 @@ -using System.Collections.Generic; using System.Linq; using FluentDate; using FluentDateTimeOffset; @@ -9,88 +8,6 @@ [TestFixture] public class LibGitExtensionsTests { - [Test] - public void NewestSemVerTag_RetrieveTheHighestSemanticVersionPointingAtTheSpecifiedCommit() - { - var mockCommit = new MockCommit(); - var repo = new MockRepository - { - Tags = new MockTagCollection - { - Tags = new List - { - new MockTag - { - NameEx = "a", - TargetEx = mockCommit, - AnnotationEx = new MockTagAnnotation - { - TaggerEx = new Signature("a", "", 7.Seconds().Ago()) - } - }, - new MockTag - { - NameEx = "9.0.0a", - TargetEx = mockCommit, - AnnotationEx = new MockTagAnnotation - { - TaggerEx = new Signature("a", "", 5.Seconds().Ago()) - } - }, - new MockTag - { - NameEx = "0.1.0", - TargetEx = mockCommit, - AnnotationEx = new MockTagAnnotation - { - TaggerEx = new Signature("a", "", 1.Seconds().Ago()) - } - }, - new MockTag - { - NameEx = "0.2.0", - TargetEx = mockCommit, - AnnotationEx = new MockTagAnnotation - { - TaggerEx = new Signature("a", "", 5.Seconds().Ago()) - } - }, - } - } - }; - - var version = repo.NewestSemVerTag(mockCommit); - - Assert.AreEqual(0, version.Major); - Assert.AreEqual(1, version.Minor); - Assert.AreEqual(0, version.Patch); - } - - [Test] - public void NewestSemVerTag_ReturnNullWhenNoTagPointingAtTheSpecifiedCommitHasBeenFound() - { - var tagNames = new[] { "a", "9.0.0", "z", "0.1.0", "11.1.0", "0.2.0" }; - - var col = new MockTagCollection(); - foreach (var tagName in tagNames) - { - col.Add(new MockTag - { - NameEx = tagName, - TargetEx = null, - AnnotationEx = new MockTagAnnotation - { - TaggerEx = new Signature("a", "", 5.Seconds().Ago()) - } - }); - } - - var repo = new MockRepository { Tags = col }; - - var version = repo.NewestSemVerTag(new MockCommit()); - - Assert.IsNull(version); - } [Test] public void TagsByDate_HonorChainedAnnotatedTags() diff --git a/GitVersionTask.Tests/Mocks/MockReferenceCollection.cs b/GitVersionTask.Tests/Mocks/MockReferenceCollection.cs index 3080f41a4d..c839d9bee7 100644 --- a/GitVersionTask.Tests/Mocks/MockReferenceCollection.cs +++ b/GitVersionTask.Tests/Mocks/MockReferenceCollection.cs @@ -15,7 +15,7 @@ public override ReflogCollection Log(string canonicalName) public List Commits = new List(); - public IEnumerator GetEnumerator() + public new IEnumerator GetEnumerator() { return Commits.GetEnumerator(); } diff --git a/GitVersionTask.Tests/Mocks/MockReflogCollection.cs b/GitVersionTask.Tests/Mocks/MockReflogCollection.cs index 6339df6c4d..d4d2b5dfe2 100644 --- a/GitVersionTask.Tests/Mocks/MockReflogCollection.cs +++ b/GitVersionTask.Tests/Mocks/MockReflogCollection.cs @@ -6,7 +6,7 @@ public class MockReflogCollection : ReflogCollection, ICollection { public List Commits = new List(); - public IEnumerator GetEnumerator() + public new IEnumerator GetEnumerator() { return Commits.GetEnumerator(); } diff --git a/GitVersionTask.Tests/UpdateAssemblyInfoTests.cs b/GitVersionTask.Tests/UpdateAssemblyInfoTests.cs index 1877f8ce67..eee7958629 100644 --- a/GitVersionTask.Tests/UpdateAssemblyInfoTests.cs +++ b/GitVersionTask.Tests/UpdateAssemblyInfoTests.cs @@ -124,7 +124,7 @@ public void SetUp() } [TearDown] - public void TearDown() + public new void TearDown() { BuildServerList.ResetSelector(); } diff --git a/GitVersionTask.Tests/VersionAndBranchFinderTests.cs b/GitVersionTask.Tests/VersionAndBranchFinderTests.cs index e56c76646c..35d8fcf801 100644 --- a/GitVersionTask.Tests/VersionAndBranchFinderTests.cs +++ b/GitVersionTask.Tests/VersionAndBranchFinderTests.cs @@ -1,5 +1,4 @@ -using GitVersion; -using LibGit2Sharp; +using LibGit2Sharp; using NUnit.Framework; [TestFixture] @@ -17,7 +16,7 @@ public void ShouldBeAbleGetVersionFromGitDir() AddOneCommitToHead(repo, "code"); } - SemanticVersion versionAndBranch; + CachedVersion versionAndBranch; VersionAndBranchFinder.TryGetVersion(ASBMTestRepoWorkingDirPath, out versionAndBranch); Assert.IsNotNull(versionAndBranch); } diff --git a/GitVersionTask.Tests/VersionOnMasterFinderTests.Should_find_previous_commit_that_was_at_least_a_minor_bump.approved.txt b/GitVersionTask.Tests/VersionOnMasterFinderTests.Should_find_previous_commit_that_was_at_least_a_minor_bump.approved.txt index fc8f418e00..ea03e7252a 100644 --- a/GitVersionTask.Tests/VersionOnMasterFinderTests.Should_find_previous_commit_that_was_at_least_a_minor_bump.approved.txt +++ b/GitVersionTask.Tests/VersionOnMasterFinderTests.Should_find_previous_commit_that_was_at_least_a_minor_bump.approved.txt @@ -1,6 +1,4 @@ { "Major": 0, - "Minor": 3, - "Timestamp": "2000-10-09T23:59:58Z", - "CommitSha": "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef" + "Minor": 3 } \ No newline at end of file diff --git a/GitVersionTask/AssemblyInfoBuilder/AssemblyInfoBuilder.cs b/GitVersionTask/AssemblyInfoBuilder/AssemblyInfoBuilder.cs index ac9ca77ee4..5f023f3f1f 100644 --- a/GitVersionTask/AssemblyInfoBuilder/AssemblyInfoBuilder.cs +++ b/GitVersionTask/AssemblyInfoBuilder/AssemblyInfoBuilder.cs @@ -4,12 +4,13 @@ public class AssemblyInfoBuilder { - public SemanticVersion SemanticVersion; + public CachedVersion CachedVersion; public AssemblyVersioningScheme AssemblyVersioningScheme; public string GetAssemblyInfoText() { - var vars = VariableProvider.GetVariablesFor(SemanticVersion); + var semanticVersion = CachedVersion.SemanticVersion; + var vars = VariableProvider.GetVariablesFor(semanticVersion); var assemblyInfo = string.Format(@" using System; using System.Reflection; @@ -39,9 +40,9 @@ static class GitVersionInformation }} -", SemanticVersion.GetAssemblyVersion(AssemblyVersioningScheme), string.Format("{0}.{1}.{2}.0", SemanticVersion.Major, SemanticVersion.Minor, SemanticVersion.Patch), SemanticVersion.ToString("i"), - SemanticVersion.BuildMetaData.ReleaseDate.OriginalDate.UtcDateTime.ToString("yyyy-MM-dd"), - SemanticVersion.BuildMetaData.ReleaseDate.Date.UtcDateTime.ToString("yyyy-MM-dd"), +", semanticVersion.GetAssemblyVersion(AssemblyVersioningScheme), string.Format("{0}.{1}.{2}.0", semanticVersion.Major, semanticVersion.Minor, semanticVersion.Patch), semanticVersion.ToString("i"), + CachedVersion.MasterReleaseDate.UtcDateTime.ToString("yyyy-MM-dd"), + semanticVersion.BuildMetaData.CommitDate.UtcDateTime.ToString("yyyy-MM-dd"), GenerateVariableMembers(vars)); return assemblyInfo; diff --git a/GitVersionTask/AssemblyInfoBuilder/UpdateAssemblyInfo.cs b/GitVersionTask/AssemblyInfoBuilder/UpdateAssemblyInfo.cs index c8649e4f56..1b62ecf360 100644 --- a/GitVersionTask/AssemblyInfoBuilder/UpdateAssemblyInfo.cs +++ b/GitVersionTask/AssemblyInfoBuilder/UpdateAssemblyInfo.cs @@ -62,7 +62,7 @@ public void InnerExecute() InvalidFileChecker.CheckForInvalidFiles(CompileFiles, ProjectFile); - SemanticVersion semanticVersion; + CachedVersion semanticVersion; if (!VersionAndBranchFinder.TryGetVersion(SolutionDirectory, out semanticVersion)) { return; @@ -98,12 +98,12 @@ AssemblyVersioningScheme GetAssemblyVersioningScheme() throw new WarningException(string.Format("Unexpected assembly versioning scheme '{0}'.", AssemblyVersioningScheme)); } - void CreateTempAssemblyInfo(SemanticVersion semanticVersion) + void CreateTempAssemblyInfo(CachedVersion semanticVersion) { var versioningScheme = GetAssemblyVersioningScheme(); var assemblyInfoBuilder = new AssemblyInfoBuilder { - SemanticVersion = semanticVersion, + CachedVersion = semanticVersion, AssemblyVersioningScheme = versioningScheme, }; var assemblyInfo = assemblyInfoBuilder.GetAssemblyInfoText(); diff --git a/GitVersionTask/CachedVersion.cs b/GitVersionTask/CachedVersion.cs new file mode 100644 index 0000000000..a52c011a29 --- /dev/null +++ b/GitVersionTask/CachedVersion.cs @@ -0,0 +1,9 @@ +using System; +using GitVersion; + +public class CachedVersion +{ + public SemanticVersion SemanticVersion; + public long Timestamp; + public DateTimeOffset MasterReleaseDate; +} \ No newline at end of file diff --git a/GitVersionTask/DirectoryDateFinder.cs b/GitVersionTask/DirectoryDateFinder.cs new file mode 100644 index 0000000000..e7be24f56c --- /dev/null +++ b/GitVersionTask/DirectoryDateFinder.cs @@ -0,0 +1,19 @@ +using System; +using System.IO; + +public static class DirectoryDateFinder +{ + public static long GetLastDirectoryWrite(string path) + { + var lastHigh = DateTime.MinValue; + foreach (var file in Directory.EnumerateDirectories(path, "*.*", SearchOption.AllDirectories)) + { + var lastWriteTime = File.GetLastWriteTime(file); + if (lastWriteTime > lastHigh) + { + lastHigh = lastWriteTime; + } + } + return lastHigh.Ticks; + } +} \ No newline at end of file diff --git a/GitVersionTask/GetVersion.cs b/GitVersionTask/GetVersion.cs index d412528b7b..5e41ceeefa 100644 --- a/GitVersionTask/GetVersion.cs +++ b/GitVersionTask/GetVersion.cs @@ -65,9 +65,6 @@ public class GetVersion : Task [Output] public string Sha { get; set; } - [Output] - public string OriginalRelease { get; set; } - [Output] public string NuGetVersionV2 { get; set; } @@ -87,11 +84,11 @@ public override bool Execute() { try { - SemanticVersion versionAndBranch; + CachedVersion versionAndBranch; if (VersionAndBranchFinder.TryGetVersion(SolutionDirectory, out versionAndBranch)) { var thisType = typeof(GetVersion); - var variables = VariableProvider.GetVariablesFor(versionAndBranch); + var variables = VariableProvider.GetVariablesFor(versionAndBranch.SemanticVersion); foreach (var variable in variables) { thisType.GetProperty(variable.Key).SetValue(this, variable.Value, null); diff --git a/GitVersionTask/GitVersionTask.csproj b/GitVersionTask/GitVersionTask.csproj index 6a47fbae09..6986c6823a 100644 --- a/GitVersionTask/GitVersionTask.csproj +++ b/GitVersionTask/GitVersionTask.csproj @@ -58,8 +58,11 @@ + + + diff --git a/GitVersionTask/VersionAndBranchFinder.cs b/GitVersionTask/VersionAndBranchFinder.cs index 3ce0449ac9..013ba7afb7 100644 --- a/GitVersionTask/VersionAndBranchFinder.cs +++ b/GitVersionTask/VersionAndBranchFinder.cs @@ -4,7 +4,7 @@ public static class VersionAndBranchFinder { static List processedDirectories = new List(); - public static bool TryGetVersion(string directory, out SemanticVersion versionAndBranch) + public static bool TryGetVersion(string directory, out CachedVersion versionAndBranch) { var gitDirectory = GitDirFinder.TreeWalkForGitDir(directory); diff --git a/GitVersionTask/VersionCache.cs b/GitVersionTask/VersionCache.cs new file mode 100644 index 0000000000..d0521a8130 --- /dev/null +++ b/GitVersionTask/VersionCache.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; +using GitVersion; + +public static class VersionCache +{ + static Dictionary versionCacheVersions = new Dictionary(); + + public static CachedVersion GetVersion(string gitDirectory) + { + using (var repo = RepositoryLoader.GetRepo(gitDirectory)) + { + var ticks = DirectoryDateFinder.GetLastDirectoryWrite(gitDirectory); + var key = string.Format("{0}:{1}:{2}", repo.Head.CanonicalName, repo.Head.Tip.Sha, ticks); + CachedVersion cachedVersion; + if (versionCacheVersions.TryGetValue(key, out cachedVersion)) + { + if (cachedVersion.Timestamp != ticks) + { + Logger.WriteInfo("Change detected. flushing cache."); + cachedVersion.SemanticVersion = GitVersionFinder.GetSemanticVersion(repo); + cachedVersion.MasterReleaseDate = LastVersionOnMasterFinder.Execute(repo, repo.Head.Tip); + } + return cachedVersion; + } + Logger.WriteInfo("Version not in cache. Calculating version."); + + //TODO: cope with githubflow + //if (GitVersionFinder.ShouldGitHubFlowVersioningSchemeApply(repo)) + //{ + // return rd; + //} + return versionCacheVersions[key] = new CachedVersion + { + SemanticVersion = GitVersionFinder.GetSemanticVersion(repo), + MasterReleaseDate = LastVersionOnMasterFinder.Execute(repo,repo.Head.Tip), + Timestamp = ticks + }; + + } + } + +} \ No newline at end of file diff --git a/GitVersionTask/WriteVersionInfoToBuildLog.cs b/GitVersionTask/WriteVersionInfoToBuildLog.cs index 8cd558ba12..84e77bc812 100644 --- a/GitVersionTask/WriteVersionInfoToBuildLog.cs +++ b/GitVersionTask/WriteVersionInfoToBuildLog.cs @@ -46,7 +46,7 @@ public override bool Execute() public void InnerExecute() { - SemanticVersion semanticVersion; + CachedVersion semanticVersion; if (!VersionAndBranchFinder.TryGetVersion(SolutionDirectory, out semanticVersion)) { return; @@ -56,14 +56,14 @@ public void InnerExecute() WriteIntegrationParameters(semanticVersion, BuildServerList.GetApplicableBuildServers(authentication)); } - public void WriteIntegrationParameters(SemanticVersion semanticVersion, IEnumerable applicableBuildServers) + public void WriteIntegrationParameters(CachedVersion semanticVersion, IEnumerable applicableBuildServers) { foreach (var buildServer in applicableBuildServers) { logger.LogInfo(string.Format("Executing GenerateSetVersionMessage for '{0}'.", buildServer.GetType().Name)); logger.LogInfo(buildServer.GenerateSetVersionMessage(semanticVersion.ToString())); logger.LogInfo(string.Format("Executing GenerateBuildLogOutput for '{0}'.", buildServer.GetType().Name)); - foreach (var buildParameter in BuildOutputFormatter.GenerateBuildLogOutput(semanticVersion, buildServer)) + foreach (var buildParameter in BuildOutputFormatter.GenerateBuildLogOutput(semanticVersion.SemanticVersion, buildServer)) { logger.LogInfo(buildParameter); } diff --git a/Packages/repositories.config b/Packages/repositories.config index c5b5940862..5b91906ea7 100644 --- a/Packages/repositories.config +++ b/Packages/repositories.config @@ -1,9 +1,11 @@  + + \ No newline at end of file diff --git a/Tests/Extensions/ExtensionMethodsTests.cs b/Tests/Extensions/ExtensionMethodsTests.cs new file mode 100644 index 0000000000..349a2a1f6e --- /dev/null +++ b/Tests/Extensions/ExtensionMethodsTests.cs @@ -0,0 +1,17 @@ +namespace Tests.Extensions +{ + using GitVersion; + using NUnit.Framework; + + [TestFixture] + public partial class ExtensionMethodsTests + { + [TestCase(0, false)] + [TestCase(1, true)] + [TestCase(2, false)] + public void IsOdd(int value, bool expectedValue) + { + Assert.AreEqual(expectedValue, value.IsOdd()); + } + } +} \ No newline at end of file diff --git a/Tests/Extensions/ExtensionMethodsTests.git.cs b/Tests/Extensions/ExtensionMethodsTests.git.cs new file mode 100644 index 0000000000..6e6feddf0b --- /dev/null +++ b/Tests/Extensions/ExtensionMethodsTests.git.cs @@ -0,0 +1,16 @@ +namespace Tests.Extensions +{ + using GitVersion; + using NUnit.Framework; + + public partial class ExtensionMethodsTests + { + [TestCase("develop", "refs/heads/develop")] + [TestCase("master", "refs/heads/master")] + [TestCase("pr/30", "refs/pull/30/head")] + public void GetCanonicalBranchName(string branchName, string expectedName) + { + Assert.AreEqual(expectedName, branchName.GetCanonicalBranchName()); + } + } +} \ No newline at end of file diff --git a/Tests/SemanticVersionPreReleaseTagTests.cs b/Tests/SemanticVersionPreReleaseTagTests.cs new file mode 100644 index 0000000000..b3716544c7 --- /dev/null +++ b/Tests/SemanticVersionPreReleaseTagTests.cs @@ -0,0 +1,7 @@ +using NUnit.Framework; + +[TestFixture] +internal class SemanticVersionPreReleaseTagTests +{ + // TODO: Write unit tests +} \ No newline at end of file