string ExtractIssueNumber(GitVersionContext context) { const string prefix = "/pull/"; var pullRequestBranch = context.CurrentBranch; var start = pullRequestBranch.CanonicalName.IndexOf(prefix, System.StringComparison.Ordinal); var end = pullRequestBranch.CanonicalName.LastIndexOf("/merge", pullRequestBranch.CanonicalName.Length - 1, System.StringComparison.Ordinal); string issueNumber = null; if (start != -1 && end != -1 && start + prefix.Length <= end) { start += prefix.Length; issueNumber = pullRequestBranch.CanonicalName.Substring(start, end - start); } if (!LooksLikeAValidPullRequestNumber(issueNumber)) { throw new WarningException(string.Format("Unable to extract pull request number from '{0}'.", pullRequestBranch.CanonicalName)); } return issueNumber; }
public SemanticVersion FindVersion(GitVersionContext context) { // If current commit is tagged, don't do anything except add build metadata if (context.IsCurrentCommitTagged) { // Will always be 0, don't bother with the +0 on tags var semanticVersionBuildMetaData = metaDataCalculator.Create(context.CurrentCommit, context); semanticVersionBuildMetaData.CommitsSinceTag = null; var semanticVersion = new SemanticVersion(context.CurrentCommitTaggedVersion) { BuildMetaData = semanticVersionBuildMetaData }; return semanticVersion; } var baseVersion = baseVersionFinder.GetBaseVersion(context); var semver = baseVersion.SemanticVersion; var increment = IncrementStrategyFinder.DetermineIncrementedField(context, baseVersion); if (increment != null) { semver = semver.IncrementVersion(increment.Value); } else Logger.WriteInfo("Skipping version increment"); if (!semver.PreReleaseTag.HasTag() && !string.IsNullOrEmpty(context.Configuration.Tag)) { UpdatePreReleaseTag(context, semver, baseVersion.BranchNameOverride); } semver.BuildMetaData = metaDataCalculator.Create(baseVersion.BaseVersionSource, context); return semver; }
public override IEnumerable<BaseVersion> GetVersions(GitVersionContext context) { var olderThan = context.CurrentCommit.When(); var allTags = context.Repository.Tags .Where(tag => ((Commit)tag.PeeledTarget()).When() <= olderThan) .ToList(); var tagsOnBranch = context.CurrentBranch .Commits .SelectMany(commit => { return allTags.Where(t => IsValidTag(t, commit)); }) .Select(t => { SemanticVersion version; if (SemanticVersion.TryParse(t.Name, context.Configuration.GitTagPrefix, out version)) { var commit = t.PeeledTarget() as Commit; if (commit != null) return new VersionTaggedCommit(commit, version, t.Name); } return null; }) .Where(a => a != null) .ToList(); return tagsOnBranch.Select(t => CreateBaseVersion(context, t)); }
public override IEnumerable<BaseVersion> GetVersions(GitVersionContext context) { var currentBranch = context.CurrentBranch; var tagPrefixRegex = context.Configuration.GitTagPrefix; var repository = context.Repository; return GetVersions(context, tagPrefixRegex, currentBranch, repository); }
public SemanticVersion FindVersion(GitVersionContext context) { if (context.CurrentBranch.IsMaster()) { return new MasterVersionFinder().FindVersion(context.Repository, context.CurrentBranch.Tip); } if (context.CurrentBranch.IsHotfix()) { return new HotfixVersionFinder().FindVersion(context); } if (context.CurrentBranch.IsRelease()) { return new ReleaseVersionFinder().FindVersion(context); } if (context.CurrentBranch.IsDevelop()) { return new DevelopVersionFinder().FindVersion(context); } if (context.CurrentBranch.IsPullRequest()) { return new PullVersionFinder().FindVersion(context); } if (context.CurrentBranch.IsSupport()) { return new SupportVersionFinder().FindVersion(context.Repository, context.CurrentBranch.Tip); } return new FeatureVersionFinder().FindVersion(context); }
public override IEnumerable<BaseVersion> GetVersions(GitVersionContext context) { if (string.IsNullOrEmpty(context.Configuration.NextVersion) || context.IsCurrentCommitTagged) yield break; var semanticVersion = SemanticVersion.Parse(context.Configuration.NextVersion, context.Configuration.GitTagPrefix); yield return new BaseVersion("NextVersion in GitVersionConfig.yaml", false, semanticVersion, null, null); }
public BaseVersion GetBaseVersion(GitVersionContext context) { Logger.WriteInfo("Base Versions:"); var baseVersion = strategies .Select(s => s.GetVersion(context)) .Where(v => { if (v != null) { Logger.WriteInfo(v.ToString()); return true; } return false; }) .Aggregate((v1, v2) => { if (v1.SemanticVersion > v2.SemanticVersion) { return new BaseVersion(v1.Source, v1.ShouldIncrement, v1.SemanticVersion, v1.BaseVersionSource ?? v2.BaseVersionSource, v1.BranchNameOverride); } return new BaseVersion(v2.Source, v2.ShouldIncrement, v2.SemanticVersion, v2.BaseVersionSource ?? v1.BaseVersionSource, v2.BranchNameOverride); }); Logger.WriteInfo(string.Format("Base version used: {0}", baseVersion)); return baseVersion; }
private IEnumerable<BaseVersion> ReleaseBranchBaseVersions(GitVersionContext context) { var releaseBranchConfig = context.FullConfiguration.Branches .Where(b => b.Value.IsReleaseBranch == true) .ToList(); if (releaseBranchConfig.Any()) { var releaseBranches = context.Repository.Branches .Where(b => releaseBranchConfig.Any(c => Regex.IsMatch(b.FriendlyName, c.Key))); return releaseBranches .SelectMany(b => GetReleaseVersion(context, b)) .Select(baseVersion => { // Need to drop branch overrides and give a bit more context about // where this version came from var source1 = "Release branch exists -> " + baseVersion.Source; return new BaseVersion(source1, baseVersion.ShouldIncrement, baseVersion.SemanticVersion, baseVersion.BaseVersionSource, null); }) .ToList(); } return new BaseVersion[0]; }
public SemanticVersion FindVersion(GitVersionContext context) { // If current commit is tagged, don't do anything except add build metadata if (context.IsCurrentCommitTagged) { // Will always be 0, don't bother with the +0 on tags var semanticVersionBuildMetaData = metaDataCalculator.Create(context.CurrentCommit, context); semanticVersionBuildMetaData.CommitsSinceTag = null; var semanticVersion = new SemanticVersion(context.CurrentCommitTaggedVersion) { BuildMetaData = semanticVersionBuildMetaData }; return semanticVersion; } var baseVersion = baseVersionFinder.GetBaseVersion(context); if (baseVersion.ShouldIncrement) IncrementVersion(context, baseVersion); else Logger.WriteInfo("Skipping version increment"); if (!baseVersion.SemanticVersion.PreReleaseTag.HasTag() && !string.IsNullOrEmpty(context.Configuration.Tag)) { UpdatePreReleaseTag(context, baseVersion); } baseVersion.SemanticVersion.BuildMetaData = metaDataCalculator.Create(baseVersion.BaseVersionSource, context); return baseVersion.SemanticVersion; }
public override IEnumerable<BaseVersion> GetVersions(GitVersionContext context) { var baseVersionSource = context.Repository.Commits.QueryBy(new CommitFilter { IncludeReachableFrom = context.CurrentBranch.Tip }).First(c => !c.Parents.Any()); yield return new BaseVersion("Fallback base version", false, new SemanticVersion(minor: 1), baseVersionSource, null); }
public SemanticVersion FindVersion(GitVersionContext context) { var repositoryDirectory = context.Repository.Info.WorkingDirectory; var lastTaggedReleaseFinder = new LastTaggedReleaseFinder(context); var nextVersionTxtFileFinder = new NextVersionTxtFileFinder(repositoryDirectory); var nextSemverCalculator = new NextSemverCalculator(nextVersionTxtFileFinder, lastTaggedReleaseFinder, context); return new BuildNumberCalculator(nextSemverCalculator, lastTaggedReleaseFinder, context.Repository).GetBuildNumber(context); }
public BaseVersion GetBaseVersion(GitVersionContext context) { using (Logger.IndentLog("Calculating base versions")) { var baseVersions = strategies .SelectMany(s => s.GetVersions(context)) .Where(v => { if (v != null) { Logger.WriteInfo(v.ToString()); return true; } return false; }) .Select(v => new { IncrementedVersion = MaybeIncrement(context, v), Version = v }) .ToList(); var maxVersion = baseVersions.Aggregate((v1, v2) => v1.IncrementedVersion > v2.IncrementedVersion ? v1 : v2); var matchingVersionsOnceIncremented = baseVersions .Where(b => b != maxVersion && b.Version.BaseVersionSource != null && b.IncrementedVersion == maxVersion.IncrementedVersion) .ToList(); BaseVersion baseVersionWithOldestSource; if (matchingVersionsOnceIncremented.Any()) { baseVersionWithOldestSource = matchingVersionsOnceIncremented.Aggregate((v1, v2) => v1.Version.BaseVersionSource.Committer.When < v2.Version.BaseVersionSource.Committer.When ? v1 : v2).Version; Logger.WriteInfo(string.Format( "Found multiple base versions which will produce the same SemVer ({0}), taking oldest source for commit counting ({1})", maxVersion.IncrementedVersion, baseVersionWithOldestSource.Source)); } else { baseVersionWithOldestSource = baseVersions .Where(v => v.Version.BaseVersionSource != null) .OrderByDescending(v => v.IncrementedVersion) .ThenByDescending(v => v.Version.BaseVersionSource.Committer.When) .First() .Version; } if (baseVersionWithOldestSource.BaseVersionSource == null) throw new Exception("Base version should not be null"); var calculatedBase = new BaseVersion( maxVersion.Version.Source, maxVersion.Version.ShouldIncrement, maxVersion.Version.SemanticVersion, baseVersionWithOldestSource.BaseVersionSource, maxVersion.Version.BranchNameOverride); Logger.WriteInfo(string.Format("Base version used: {0}", calculatedBase)); return calculatedBase; } }
public SemanticVersion FindVersion(GitVersionContext context) { var issueNumber = ExtractIssueNumber(context); var version = FindVersion(context, BranchType.PullRequest); version.PreReleaseTag = new SemanticVersionPreReleaseTag("PullRequest", int.Parse(issueNumber)); //TODO version.Version.BuildMetaData = NumberOfCommitsOnBranchSinceCommit(context.CurrentBranch, commonAncestor); return version; }
public override IEnumerable<BaseVersion> GetVersions(GitVersionContext context) { if (context.Configuration.IsCurrentBranchDevelop) { return ReleaseBranchBaseVersions(context).Union(MasterTagsVersions(context)); } return new BaseVersion[0]; }
IEnumerable<BaseVersion> GetReleaseVersion(GitVersionContext context, Branch releaseBranch) { var tagPrefixRegex = context.Configuration.GitTagPrefix; var repository = context.Repository; var baseSource = releaseBranch.FindMergeBase(context.CurrentBranch, repository); return releaseVersionStrategy .GetVersions(tagPrefixRegex, releaseBranch, repository) .Select(b => new BaseVersion(b.Source, true, b.SemanticVersion, baseSource, b.BranchNameOverride)); }
public BaseVersion(GitVersionContext context, string source, bool shouldIncrement, SemanticVersion semanticVersion, Commit baseVersionSource, string branchNameOverride) { Source = source; ShouldIncrement = shouldIncrement; SemanticVersion = semanticVersion; BaseVersionSource = baseVersionSource; BranchNameOverride = branchNameOverride; _context = context; }
public override IEnumerable<BaseVersion> GetVersions(GitVersionContext context) { var versionInBranch = GetVersionInBranch(context); if (versionInBranch != null) { var commitBranchWasBranchedFrom = context.CurrentBranch.FindCommitBranchWasBranchedFrom(context.Repository); var branchNameOverride = context.CurrentBranch.Name.RegexReplace("[-/]" + versionInBranch.Item1, string.Empty); yield return new BaseVersion("Version in branch name", false, versionInBranch.Item2, commitBranchWasBranchedFrom, branchNameOverride); } }
private IEnumerable<BaseVersion> MasterTagsVersions(GitVersionContext context) { var master = context.Repository.FindBranch("master"); if (master != null) { return taggedCommitVersionStrategy.GetTaggedVersions(context, master, null); } return new BaseVersion[0]; }
static SemanticVersion MaybeIncrement(GitVersionContext context, BaseVersion version) { var increment = IncrementStrategyFinder.DetermineIncrementedField(context, version); if (increment != null) { return version.SemanticVersion.IncrementVersion(increment.Value); } return version.SemanticVersion; }
public IEnumerable<BaseVersion> GetVersions(GitVersionContext context, string tagPrefixRegex, Branch currentBranch, IRepository repository) { var branchName = currentBranch.FriendlyName; var versionInBranch = GetVersionInBranch(branchName, tagPrefixRegex); if (versionInBranch != null) { var commitBranchWasBranchedFrom = currentBranch.FindCommitBranchWasBranchedFrom(repository); var branchNameOverride = branchName.RegexReplace("[-/]" + versionInBranch.Item1, string.Empty); yield return new BaseVersion(context, "Version in branch name", false, versionInBranch.Item2, commitBranchWasBranchedFrom.Commit, branchNameOverride); } }
public override BaseVersion GetVersion(GitVersionContext context) { VersionTaggedCommit version; if (GetVersion(context, out version)) { var shouldUpdateVersion = version.Commit.Sha != context.CurrentCommit.Sha; return new BaseVersion(string.Format("Git tag '{0}'", version.Tag), shouldUpdateVersion, version.SemVer, version.Commit, null); } return null; }
private static SemanticVersion PerformIncrement(GitVersionContext context, BaseVersion baseVersion) { var semver = baseVersion.SemanticVersion; var increment = IncrementStrategyFinder.DetermineIncrementedField(context, baseVersion); if (increment != null) { semver = semver.IncrementVersion(increment.Value); } else Logger.WriteInfo("Skipping version increment"); return semver; }
string ExtractIssueNumber(GitVersionContext context) { var issueNumber = GitHelper.ExtractIssueNumber(context.CurrentBranch.CanonicalName); if (!GitHelper.LooksLikeAValidPullRequestNumber(issueNumber)) { throw new WarningException(string.Format("Unable to extract pull request number from '{0}'.", context.CurrentBranch.CanonicalName)); } return issueNumber; }
public override BaseVersion GetVersion(GitVersionContext context) { var versionInBranch = GetVersionInBranch(context); if (versionInBranch != null) { var commitBranchWasBranchedFrom = context.CurrentBranch.FindCommitBranchWasBranchedFrom(context.Repository, context.OnlyEvaluateTrackedBranches); var branchNameOverride = context.CurrentBranch.Name.RegexReplace("[-/]" + versionInBranch.Item1, string.Empty); return new BaseVersion("Version in branch name", false, versionInBranch.Item2, commitBranchWasBranchedFrom, branchNameOverride); } return null; }
protected override bool IsValidTag(GitVersionContext context, string branchName, Tag tag, Commit commit) { if (!string.IsNullOrWhiteSpace(branchName)) { if (context.Configuration.TrackMergeTarget) { return IsDirectMergeFromCommit(tag, commit); } } return base.IsValidTag(context, branchName, tag, commit); }
void UpdatePreReleaseTag(GitVersionContext context, SemanticVersion semanticVersion, string branchNameOverride) { var tagToUse = context.Configuration.Tag; if (tagToUse == "useBranchName") { tagToUse = "{BranchName}"; } if (tagToUse.Contains("{BranchName}")) { Logger.WriteInfo("Using branch name to calculate version tag"); var branchName = branchNameOverride ?? context.CurrentBranch.FriendlyName; if (!string.IsNullOrWhiteSpace(context.Configuration.BranchPrefixToTrim)) { branchName = branchName.RegexReplace(context.Configuration.BranchPrefixToTrim, string.Empty, RegexOptions.IgnoreCase); } branchName = branchName.RegexReplace("[^a-zA-Z0-9-]", "-"); tagToUse = tagToUse.Replace("{BranchName}", branchName); } int? number = null; if (!string.IsNullOrEmpty(context.Configuration.TagNumberPattern)) { var match = Regex.Match(context.CurrentBranch.CanonicalName, context.Configuration.TagNumberPattern); var numberGroup = match.Groups["number"]; if (numberGroup.Success) { number = int.Parse(numberGroup.Value); } } var lastTag = context.CurrentBranch .GetVersionTagsOnBranch(context.Repository, context.Configuration.GitTagPrefix) .FirstOrDefault(v => v.PreReleaseTag.Name == tagToUse); if (number == null && lastTag != null && MajorMinorPatchEqual(lastTag, semanticVersion) && lastTag.PreReleaseTag.HasTag()) { number = lastTag.PreReleaseTag.Number + 1; } if (number == null) { number = 1; } semanticVersion.PreReleaseTag = new SemanticVersionPreReleaseTag(tagToUse, number); }
Tuple<string, SemanticVersion> GetVersionInBranch(GitVersionContext context) { var branchParts = context.CurrentBranch.Name.Split('/', '-'); foreach (var part in branchParts) { SemanticVersion semanticVersion; if (SemanticVersion.TryParse(part, context.Configuration.GitTagPrefix, out semanticVersion)) { return Tuple.Create(part, semanticVersion); } } return null; }
public override IEnumerable<BaseVersion> GetVersions(GitVersionContext context) { string currentBranchName = null; var head = context.Repository.Head; if (head != null) { currentBranchName = head.CanonicalName; } var olderThan = context.CurrentCommit.When(); var allTags = context.Repository.Tags .Where(tag => ((Commit)tag.PeeledTarget()).When() <= olderThan) .ToList(); var tagsOnBranch = context.CurrentBranch .Commits .SelectMany(commit => { return allTags.Where(t => IsValidTag(context, currentBranchName, t, commit)); }) .Select(t => { SemanticVersion version; if (SemanticVersion.TryParse(t.Name, context.Configuration.GitTagPrefix, out version)) { var commit = t.PeeledTarget() as Commit; if (commit != null) return new VersionTaggedCommit(commit, version, t.Name); } return null; }) .Where(a => a != null) .ToList(); if (tagsOnBranch.Count == 0) { yield break; } if (tagsOnBranch.Count == 1) { yield return CreateBaseVersion(context, tagsOnBranch[0]); } foreach (var result in tagsOnBranch.Select(t => CreateBaseVersion(context, t))) { yield return result; } }
static SemanticVersionPreReleaseTag RetrieveMostRecentOptionalTagVersion(GitVersionContext context, List<Tag> applicableTagsInDescendingOrder) { if (applicableTagsInDescendingOrder.Any()) { var taggedCommit = applicableTagsInDescendingOrder.First().PeeledTarget(); var preReleaseVersion = applicableTagsInDescendingOrder.Select(tag => SemanticVersion.Parse(tag.FriendlyName, context.Configuration.GitTagPrefix)).FirstOrDefault(); if (preReleaseVersion != null) { if (taggedCommit != context.CurrentCommit) { preReleaseVersion.PreReleaseTag.Number++; } return preReleaseVersion.PreReleaseTag; } } return null; }
IEnumerable<BaseVersion> GetReleaseVersion(GitVersionContext context, Branch releaseBranch) { var tagPrefixRegex = context.Configuration.GitTagPrefix; var repository = context.Repository; // Find the commit where the child branch was created. var baseSource = context.RepositoryMetadataProvider.FindMergeBase(releaseBranch, context.CurrentBranch); if (baseSource == context.CurrentCommit) { // Ignore the branch if it has no commits. return new BaseVersion[0]; } return releaseVersionStrategy .GetVersions(context, tagPrefixRegex, releaseBranch, repository) .Select(b => new BaseVersion(context, b.Source, true, b.SemanticVersion, baseSource, b.BranchNameOverride)); }
private void FixTheBaseVersionSourceOfMergeMessageStrategyIfReleaseBranchWasMergedAndDeleted( GitVersionContext context, List <Versions> baseVersions) { if (!ReleaseBranchExistsInRepo(context)) { foreach (var baseVersion in baseVersions) { if (baseVersion.Version.Source.Contains( MergeMessageBaseVersionStrategy.MergeMessageStrategyPrefix) && baseVersion.Version.Source.Contains("Merge branch") && baseVersion.Version.Source.Contains("release")) { var parents = baseVersion.Version.BaseVersionSource.Parents.ToList(); baseVersion.Version = new BaseVersion( context, baseVersion.Version.Source, baseVersion.Version.ShouldIncrement, baseVersion.Version.SemanticVersion, context.Repository.ObjectDatabase.FindMergeBase(parents[0], parents[1]), baseVersion.Version.BranchNameOverride); } } } }
public SemanticVersionBuildMetaData Create(Commit baseVersionSource, GitVersionContext context) { var qf = new CommitFilter { IncludeReachableFrom = context.CurrentCommit, ExcludeReachableFrom = baseVersionSource, SortBy = CommitSortStrategies.Topological | CommitSortStrategies.Time }; var commitLog = context.Repository.Commits.QueryBy(qf); var commitsSinceTag = commitLog.Count(); context.Log.Info($"{commitsSinceTag} commits found between {baseVersionSource.Sha} and {context.CurrentCommit.Sha}"); var shortSha = context.Repository.ObjectDatabase.ShortenObjectId(context.CurrentCommit); return(new SemanticVersionBuildMetaData( baseVersionSource.Sha, commitsSinceTag, context.CurrentBranch.FriendlyName, context.CurrentCommit.Sha, shortSha, context.CurrentCommit.When())); }
void UpdatePreReleaseTag(GitVersionContext context, SemanticVersion semanticVersion, string branchNameOverride) { var tagToUse = GetBranchSpecificTag(context.Configuration, context.CurrentBranch.FriendlyName, branchNameOverride); int?number = null; var lastTag = context.RepositoryMetadataProvider .GetVersionTagsOnBranch(context.CurrentBranch, context.Configuration.GitTagPrefix) .FirstOrDefault(v => v.PreReleaseTag.Name == tagToUse); if (lastTag != null && MajorMinorPatchEqual(lastTag, semanticVersion) && lastTag.PreReleaseTag.HasTag()) { number = lastTag.PreReleaseTag.Number + 1; } if (number == null) { number = 1; } semanticVersion.PreReleaseTag = new SemanticVersionPreReleaseTag(tagToUse, number); }
public override BaseVersion GetVersion(GitVersionContext context) { return(new BaseVersion("Source 1", false, new SemanticVersion(1), when, null)); }
public override BaseVersion GetVersion(GitVersionContext context) { return(new BaseVersion("Source 2", true, new SemanticVersion(2), when, null)); }
public abstract SemanticVersionPreReleaseTag GetPreReleaseTag(GitVersionContext context, List <Tag> possibleTags, int numberOfCommits);
public override IEnumerable <BaseVersion> GetVersions(GitVersionContext context) { return(GetTaggedVersions(context, context.CurrentBranch, context.CurrentCommit.When())); }
/// <summary> /// Calculates the <see cref="BaseVersion"/> values for the given <paramref name="context"/>. /// </summary> /// <param name="context"> /// The context for calculating the <see cref="BaseVersion"/>. /// </param> /// <returns> /// An <see cref="IEnumerable{BaseVersion}"/> of the base version values found by the strategy. /// </returns> public abstract IEnumerable <BaseVersion> GetVersions(GitVersionContext context);
private static bool TryParse(Commit mergeCommit, GitVersionContext context, out MergeMessage mergeMessage) { mergeMessage = Inner(mergeCommit, context); return(mergeMessage != null); }
public BaseVersion GetBaseVersion(GitVersionContext context) { using (Logger.IndentLog("Calculating base versions")) { var baseVersions = strategies .SelectMany(s => s.GetVersions(context)) .Where(v => { if (v == null) { return(false); } Logger.WriteInfo(v.ToString()); foreach (var filter in context.Configuration.VersionFilters) { string reason; if (filter.Exclude(v, out reason)) { Logger.WriteInfo(reason); return(false); } } return(true); }) .Select(v => new { IncrementedVersion = MaybeIncrement(context, v), Version = v }) .ToList(); var maxVersion = baseVersions.Aggregate((v1, v2) => v1.IncrementedVersion > v2.IncrementedVersion ? v1 : v2); var matchingVersionsOnceIncremented = baseVersions .Where(b => b.Version.BaseVersionSource != null && b.IncrementedVersion == maxVersion.IncrementedVersion) .ToList(); BaseVersion baseVersionWithOldestSource; if (matchingVersionsOnceIncremented.Any()) { baseVersionWithOldestSource = matchingVersionsOnceIncremented.Aggregate((v1, v2) => v1.Version.BaseVersionSource.Committer.When < v2.Version.BaseVersionSource.Committer.When ? v1 : v2).Version; Logger.WriteInfo(string.Format( "Found multiple base versions which will produce the same SemVer ({0}), taking oldest source for commit counting ({1})", maxVersion.IncrementedVersion, baseVersionWithOldestSource.Source)); } else { baseVersionWithOldestSource = baseVersions .Where(v => v.Version.BaseVersionSource != null) .OrderByDescending(v => v.IncrementedVersion) .ThenByDescending(v => v.Version.BaseVersionSource.Committer.When) .First() .Version; } if (baseVersionWithOldestSource.BaseVersionSource == null) { throw new Exception("Base version should not be null"); } var calculatedBase = new BaseVersion( maxVersion.Version.Source, maxVersion.Version.ShouldIncrement, maxVersion.Version.SemanticVersion, baseVersionWithOldestSource.BaseVersionSource, maxVersion.Version.BranchNameOverride); Logger.WriteInfo(string.Format("Base version used: {0}", calculatedBase)); return(calculatedBase); } }
// TODO I think we need to take a fresh approach to this.. it's getting really complex with heaps of edge cases static BranchConfig InheritBranchConfiguration(GitVersionContext context, Branch targetBranch, BranchConfig branchConfiguration, IList <Branch> excludedInheritBranches) { var repository = context.Repository; var config = context.FullConfiguration; using (Logger.IndentLog("Attempting to inherit branch configuration from parent branch")) { var excludedBranches = new[] { targetBranch }; // Check if we are a merge commit. If so likely we are a pull request var parentCount = context.CurrentCommit.Parents.Count(); if (parentCount == 2) { excludedBranches = CalculateWhenMultipleParents(repository, context.CurrentCommit, ref targetBranch, excludedBranches); } if (excludedInheritBranches == null) { excludedInheritBranches = repository.Branches.Where(b => { var branchConfig = config.GetConfigForBranch(b.NameWithoutRemote()); return(branchConfig == null || branchConfig.Increment == IncrementStrategy.Inherit); }).ToList(); } // Add new excluded branches. foreach (var excludedBranch in excludedBranches.ExcludingBranches(excludedInheritBranches)) { excludedInheritBranches.Add(excludedBranch); } var branchesToEvaluate = repository.Branches.ExcludingBranches(excludedInheritBranches).ToList(); var branchPoint = context.RepositoryMetadataProvider .FindCommitBranchWasBranchedFrom(targetBranch, excludedInheritBranches.ToArray()); List <Branch> possibleParents; if (branchPoint == BranchCommit.Empty) { possibleParents = context.RepositoryMetadataProvider.GetBranchesContainingCommit(targetBranch.Tip, branchesToEvaluate, true) // It fails to inherit Increment branch configuration if more than 1 parent; // therefore no point to get more than 2 parents .Take(2) .ToList(); } else { var branches = context.RepositoryMetadataProvider .GetBranchesContainingCommit(branchPoint.Commit, branchesToEvaluate, true).ToList(); if (branches.Count > 1) { var currentTipBranches = context.RepositoryMetadataProvider .GetBranchesContainingCommit(context.CurrentCommit, branchesToEvaluate, true).ToList(); possibleParents = branches.Except(currentTipBranches).ToList(); } else { possibleParents = branches; } } Logger.WriteInfo("Found possible parent branches: " + string.Join(", ", possibleParents.Select(p => p.FriendlyName))); if (possibleParents.Count == 1) { var branchConfig = GetBranchConfiguration(context, possibleParents[0], excludedInheritBranches); // If we have resolved a fallback config we should not return that we have got config if (branchConfig.Name != FallbackConfigName) { return(new BranchConfig(branchConfiguration) { Increment = branchConfig.Increment, PreventIncrementOfMergedBranchVersion = branchConfig.PreventIncrementOfMergedBranchVersion, // If we are inheriting from develop then we should behave like develop TracksReleaseBranches = branchConfig.TracksReleaseBranches }); } } // If we fail to inherit it is probably because the branch has been merged and we can't do much. So we will fall back to develop's config // if develop exists and master if not string errorMessage; if (possibleParents.Count == 0) { errorMessage = "Failed to inherit Increment branch configuration, no branches found."; } else { errorMessage = "Failed to inherit Increment branch configuration, ended up with: " + string.Join(", ", possibleParents.Select(p => p.FriendlyName)); } var developBranchRegex = config.Branches[ConfigurationProvider.DevelopBranchKey].Regex; var masterBranchRegex = config.Branches[ConfigurationProvider.MasterBranchKey].Regex; var chosenBranch = repository.Branches.FirstOrDefault(b => Regex.IsMatch(b.FriendlyName, developBranchRegex, RegexOptions.IgnoreCase) || Regex.IsMatch(b.FriendlyName, masterBranchRegex, RegexOptions.IgnoreCase)); if (chosenBranch == null) { // TODO We should call the build server to generate this exception, each build server works differently // for fetch issues and we could give better warnings. throw new InvalidOperationException("Could not find a 'develop' or 'master' branch, neither locally nor remotely."); } var branchName = chosenBranch.FriendlyName; Logger.WriteWarning(errorMessage + Environment.NewLine + Environment.NewLine + "Falling back to " + branchName + " branch config"); // To prevent infinite loops, make sure that a new branch was chosen. if (targetBranch.IsSameBranch(chosenBranch)) { BranchConfig developOrMasterConfig = ChooseMasterOrDevelopIncrementStrategyIfTheChosenBranchIsOneOfThem( chosenBranch, branchConfiguration, config); if (developOrMasterConfig != null) { return(developOrMasterConfig); } else { Logger.WriteWarning("Fallback branch wants to inherit Increment branch configuration from itself. Using patch increment instead."); return(new BranchConfig(branchConfiguration) { Increment = IncrementStrategy.Patch }); } } var inheritingBranchConfig = GetBranchConfiguration(context, chosenBranch, excludedInheritBranches); var configIncrement = inheritingBranchConfig.Increment; if (inheritingBranchConfig.Name == FallbackConfigName && configIncrement == IncrementStrategy.Inherit) { Logger.WriteWarning("Fallback config inherits by default, dropping to patch increment"); configIncrement = IncrementStrategy.Patch; } return(new BranchConfig(branchConfiguration) { Increment = configIncrement, PreventIncrementOfMergedBranchVersion = inheritingBranchConfig.PreventIncrementOfMergedBranchVersion, // If we are inheriting from develop then we should behave like develop TracksReleaseBranches = inheritingBranchConfig.TracksReleaseBranches }); } }
public override SemanticVersionPreReleaseTag GetPreReleaseTag(GitVersionContext context, List <Tag> possibleTags, int numberOfCommits) { return(context.Configuration.Tag + "." + numberOfCommits); }
public SemanticVersion FindMainlineModeVersion(BaseVersion baseVersion, GitVersionContext context) { if (baseVersion.SemanticVersion.PreReleaseTag.HasTag()) { throw new NotSupportedException("Mainline development mode doesn't yet support pre-release tags on master"); } using (Logger.IndentLog("Using mainline development mode to calculate current version")) { var mainlineVersion = baseVersion.SemanticVersion; // Forward merge / PR // * feature/foo // / | // master * * // var mainlineTip = GetMainlineTip(context); var commitsNotOnMainline = context.Repository.Commits.QueryByPath(context.PathFilter, new CommitFilter { IncludeReachableFrom = context.CurrentBranch, ExcludeReachableFrom = mainlineTip, SortBy = CommitSortStrategies.Time, FirstParentOnly = true }).Where(c => c.Sha != baseVersion.BaseVersionSource.Sha && c.Parents.Count() == 1).ToList(); var commitLog = context.Repository.Commits.QueryByPath(context.PathFilter, new CommitFilter { IncludeReachableFrom = context.CurrentBranch, ExcludeReachableFrom = baseVersion.BaseVersionSource, SortBy = CommitSortStrategies.Time, FirstParentOnly = true }) .Where(c => c.Sha != baseVersion.BaseVersionSource.Sha) .Except(commitsNotOnMainline) .ToList(); commitLog.Reverse(); var directCommits = new List <Commit>(); // Scans commit log in reverse, aggregating merge commits foreach (var commit in commitLog) { directCommits.Add(commit); if (commit.Parents.Count() > 1) { mainlineVersion = AggregateMergeCommitIncrement(context, commit, directCommits, mainlineVersion); } } if (context.CurrentBranch.FriendlyName != "master") { var mergedHead = context.CurrentCommit; var findMergeBase = context.Repository.ObjectDatabase.FindMergeBase(context.CurrentCommit, mainlineTip); Logger.WriteInfo(string.Format("Current branch ({0}) was branch from {1}", context.CurrentBranch.FriendlyName, findMergeBase)); var branchIncrement = FindMessageIncrement(context, null, mergedHead, findMergeBase, directCommits); // This will increment for any direct commits on master mainlineVersion = IncrementForEachCommit(context, directCommits, mainlineVersion, "master"); mainlineVersion.BuildMetaData = metaDataCalculator.Create(findMergeBase, context); // Don't increment if the merge commit is a merge into mainline // this ensures PR's and forward merges end up correct. if (mergedHead.Parents.Count() == 1 || mergedHead.Parents.First() != mainlineTip) { Logger.WriteInfo(string.Format("Performing {0} increment for current branch ", branchIncrement)); mainlineVersion = mainlineVersion.IncrementVersion(branchIncrement); } } else { // If we are on master, make sure no commits get left behind mainlineVersion = IncrementForEachCommit(context, directCommits, mainlineVersion); mainlineVersion.BuildMetaData = metaDataCalculator.Create(baseVersion.BaseVersionSource, context); } return(mainlineVersion); } }
public SemanticVersion FindMainlineModeVersion(BaseVersion baseVersion, GitVersionContext context) { if (baseVersion.SemanticVersion.PreReleaseTag.HasTag()) { throw new NotSupportedException("Mainline development mode doesn't yet support pre-release tags on master"); } using (Logger.IndentLog("Using mainline development mode to calculate current version")) { var mainlineVersion = baseVersion.SemanticVersion; // Forward merge / PR // * feature/foo // / | // master * * // var mergeBase = baseVersion.BaseVersionSource; var mainline = GetMainline(context, baseVersion.BaseVersionSource); var mainlineTip = mainline.Tip; // when the current branch is not mainline, find the effective mainline tip for versioning the branch if (!context.CurrentBranch.IsSameBranch(mainline)) { mergeBase = FindMergeBaseBeforeForwardMerge(context, baseVersion.BaseVersionSource, mainline, out mainlineTip); Logger.WriteInfo($"Current branch ({context.CurrentBranch.FriendlyName}) was branch from {mergeBase}"); } var mainlineCommitLog = context.Repository.Commits.QueryBy(new CommitFilter { IncludeReachableFrom = mainlineTip, ExcludeReachableFrom = baseVersion.BaseVersionSource, SortBy = CommitSortStrategies.Reverse, FirstParentOnly = true }) .ToList(); var directCommits = new List <Commit>(mainlineCommitLog.Count); // Scans commit log in reverse, aggregating merge commits foreach (var commit in mainlineCommitLog) { directCommits.Add(commit); if (commit.Parents.Count() > 1) { mainlineVersion = AggregateMergeCommitIncrement(context, commit, directCommits, mainlineVersion, mainline); } } // This will increment for any direct commits on mainline mainlineVersion = IncrementForEachCommit(context, directCommits, mainlineVersion, mainline); mainlineVersion.BuildMetaData = metaDataCalculator.Create(mergeBase, context); // branches other than master always get a bump for the act of branching if (context.CurrentBranch.FriendlyName != "master") { var branchIncrement = FindMessageIncrement(context, null, context.CurrentCommit, mergeBase, mainlineCommitLog); Logger.WriteInfo($"Performing {branchIncrement} increment for current branch "); mainlineVersion = mainlineVersion.IncrementVersion(branchIncrement); } return(mainlineVersion); } }
public BranchConfigurationCalculator(ILog log, GitVersionContext context) { this.log = log ?? throw new ArgumentNullException(nameof(log)); this.context = context; }
public override IEnumerable <BaseVersion> GetVersions(GitVersionContext context) { return(versions); }
public override IEnumerable <BaseVersion> GetVersions(GitVersionContext context) { yield return(new BaseVersion(context, "Source 2", true, new SemanticVersion(2), when, null)); }
public override IEnumerable <BaseVersion> GetVersions(GitVersionContext context) { yield return(new BaseVersion("Source 1", false, new SemanticVersion(1), when, null)); }
public BaseVersion GetBaseVersion(GitVersionContext context) { return(new BaseVersion(context, "Test source", shouldIncrement, semanticVersion, source, null)); }
public virtual IEnumerable <BaseVersion> GetVersions(GitVersionContext context) { return(versions); }
public SemanticVersion FindVersion(GitVersionContext context) { return(FindVersion(context, BranchType.Hotfix, "master")); }
static SemanticVersion MaybeIncrement(GitVersionContext context, BaseVersion version) { return(version.ShouldIncrement ? version.SemanticVersion.IncrementVersion(context.Configuration.Increment) : version.SemanticVersion); }
protected virtual bool IsValidTag(GitVersionContext context, string branchName, Tag tag, Commit commit) { return(tag.PeeledTarget() == commit); }
static SemanticVersion ExecuteGitVersion(GitVersionContext context) { var vf = new GitVersionFinder(); return(vf.FindVersion(context)); }
public SemanticVersionBuildMetaData Create(Commit baseVersionSource, GitVersionContext context) { return(metaData); }
public override BaseVersion GetVersion(GitVersionContext context) { return(new BaseVersion("Fallback base version", false, new SemanticVersion(minor: 1), context.CurrentBranch.Commits.Last(), null)); }
static Branch GetMainline(GitVersionContext context, Commit baseVersionSource) { var mainlineBranchConfigs = context.FullConfiguration.Branches.Where(b => b.Value.IsMainline == true).ToList(); var mainlineBranches = context.Repository.Branches .Where(b => { return(mainlineBranchConfigs.Any(c => Regex.IsMatch(b.FriendlyName, c.Value.Regex))); }) .Select(b => new { MergeBase = context.Repository.ObjectDatabase.FindMergeBase(b.Tip, context.CurrentCommit), Branch = b }) .Where(a => a.MergeBase != null) .GroupBy(b => b.MergeBase.Sha, b => b.Branch) .ToDictionary(b => b.Key, b => b.ToList()); var allMainlines = mainlineBranches.Values.SelectMany(branches => branches.Select(b => b.FriendlyName)); Logger.WriteInfo("Found possible mainline branches: " + string.Join(", ", allMainlines)); // Find closest mainline branch var firstMatchingCommit = context.CurrentBranch.Commits.First(c => mainlineBranches.ContainsKey(c.Sha)); var possibleMainlineBranches = mainlineBranches[firstMatchingCommit.Sha]; if (possibleMainlineBranches.Count == 1) { var mainlineBranch = possibleMainlineBranches[0]; Logger.WriteInfo("Mainline for current branch is " + mainlineBranch.FriendlyName); return(mainlineBranch); } // prefer current branch, if it is a mainline branch if (possibleMainlineBranches.Any(context.CurrentBranch.IsSameBranch)) { Logger.WriteInfo($"Choosing {context.CurrentBranch.FriendlyName} as mainline because it is the current branch"); return(context.CurrentBranch); } // prefer a branch on which the merge base was a direct commit, if there is such a branch var firstMatchingCommitBranch = possibleMainlineBranches .FirstOrDefault(b => { var filter = new CommitFilter { IncludeReachableFrom = b, ExcludeReachableFrom = baseVersionSource, FirstParentOnly = true, }; var query = context.Repository.Commits.QueryBy(filter); return(query.Contains(firstMatchingCommit)); }); if (firstMatchingCommitBranch != null) { var message = string.Format( "Choosing {0} as mainline because {1}'s merge base was a direct commit to {0}", firstMatchingCommitBranch.FriendlyName, context.CurrentBranch.FriendlyName); Logger.WriteInfo(message); return(firstMatchingCommitBranch); } var chosenMainline = possibleMainlineBranches[0]; Logger.WriteInfo($"Multiple mainlines ({string.Join(", ", possibleMainlineBranches.Select(b => b.FriendlyName))}) have the same merge base for the current branch, choosing {chosenMainline.FriendlyName} because we found that branch first..."); return(chosenMainline); }
private static SemanticVersionPreReleaseTag RetrieveMostRecentOptionalTagVersion(GitVersionContext context, IReadOnlyCollection <Tag> applicableTagsInDescendingOrder) { if (applicableTagsInDescendingOrder.Any()) { var taggedCommit = applicableTagsInDescendingOrder.First().PeeledTarget(); var preReleaseVersion = applicableTagsInDescendingOrder.Select(tag => SemanticVersion.Parse(tag.FriendlyName, context.Configuration.GitTagPrefix)).FirstOrDefault(); if (preReleaseVersion != null) { if (taggedCommit != context.CurrentCommit) { preReleaseVersion.PreReleaseTag.Number++; } return(preReleaseVersion.PreReleaseTag); } } return(null); }
private static VersionField TryFindIncrementFromMergeMessage(Commit mergeCommit, GitVersionContext context) { if (mergeCommit != null) { var mergeMessage = new MergeMessage(mergeCommit.Message, context.FullConfiguration); if (mergeMessage.MergedBranch != null) { var config = context.FullConfiguration.GetConfigForBranch(mergeMessage.MergedBranch); if (config != null && config.Increment.HasValue && config.Increment != IncrementStrategy.Inherit) { return(config.Increment.Value.ToVersionField()); } } } // Fallback to config increment value return(IncrementStrategyFinder.FindDefaultIncrementForBranch(context)); }
public override SemanticVersionPreReleaseTag GetPreReleaseTag(GitVersionContext context, List <Tag> possibleCommits, int numberOfCommits) { return(RetrieveMostRecentOptionalTagVersion(context, possibleCommits) ?? context.Configuration.Tag + ".1"); }