public GitVersionContext Create(GitVersionOptions gitVersionOptions) { var currentBranch = repositoryStore.GetTargetBranch(gitVersionOptions.RepositoryInfo.TargetBranch); if (currentBranch == null) { throw new InvalidOperationException("Need a branch to operate on"); } var configuration = configProvider.Provide(overrideConfig: options.Value.ConfigInfo.OverrideConfig); var currentCommit = repositoryStore.GetCurrentCommit(currentBranch, gitVersionOptions.RepositoryInfo.CommitId); if (currentBranch.IsDetachedHead) { var branchForCommit = repositoryStore.GetBranchesContainingCommit(currentCommit, onlyTrackedBranches: gitVersionOptions.Settings.OnlyTrackedBranches).OnlyOrDefault(); currentBranch = branchForCommit ?? currentBranch; } var currentBranchConfig = branchConfigurationCalculator.GetBranchConfiguration(currentBranch, currentCommit, configuration); var effectiveConfiguration = configuration.CalculateEffectiveConfiguration(currentBranchConfig); var currentCommitTaggedVersion = repositoryStore.GetCurrentCommitTaggedVersion(currentCommit, effectiveConfiguration); var numberOfUncommittedChanges = repositoryStore.GetNumberOfUncommittedChanges(); return(new GitVersionContext(currentBranch, currentCommit, configuration, effectiveConfiguration, currentCommitTaggedVersion, numberOfUncommittedChanges)); }
// TODO I think we need to take a fresh approach to this.. it's getting really complex with heaps of edge cases private BranchConfig InheritBranchConfiguration(IBranch targetBranch, BranchConfig branchConfiguration, ICommit currentCommit, Config configuration, IList <IBranch> excludedInheritBranches) { using (log.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 = currentCommit.Parents.Count(); if (parentCount == 2) { excludedBranches = CalculateWhenMultipleParents(currentCommit, ref targetBranch, excludedBranches); } excludedInheritBranches ??= repositoryStore.GetExcludedInheritBranches(configuration).ToList(); excludedBranches = excludedBranches.Where(b => excludedInheritBranches.All(bte => !b.Equals(bte))).ToArray(); // Add new excluded branches. foreach (var excludedBranch in excludedBranches) { excludedInheritBranches.Add(excludedBranch); } var branchesToEvaluate = repositoryStore.ExcludingBranches(excludedInheritBranches).ToList(); var branchPoint = repositoryStore .FindCommitBranchWasBranchedFrom(targetBranch, configuration, excludedInheritBranches.ToArray()); List <IBranch> possibleParents; if (branchPoint == BranchCommit.Empty) { possibleParents = repositoryStore.GetBranchesContainingCommit(targetBranch.Tip, branchesToEvaluate) // 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 = repositoryStore.GetBranchesContainingCommit(branchPoint.Commit, branchesToEvaluate).ToList(); if (branches.Count > 1) { var currentTipBranches = repositoryStore.GetBranchesContainingCommit(currentCommit, branchesToEvaluate).ToList(); possibleParents = branches.Except(currentTipBranches).ToList(); } else { possibleParents = branches; } } log.Info("Found possible parent branches: " + string.Join(", ", possibleParents.Select(p => p.ToString()))); if (possibleParents.Count == 1) { var branchConfig = GetBranchConfiguration(possibleParents[0], currentCommit, configuration, 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 main if not var errorMessage = possibleParents.Count == 0 ? "Failed to inherit Increment branch configuration, no branches found." : "Failed to inherit Increment branch configuration, ended up with: " + string.Join(", ", possibleParents.Select(p => p.ToString())); var chosenBranch = repositoryStore.GetChosenBranch(configuration); 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 'main' branch, neither locally nor remotely."); } log.Warning($"{errorMessage}{System.Environment.NewLine}Falling back to {chosenBranch} branch config"); // To prevent infinite loops, make sure that a new branch was chosen. if (targetBranch.Equals(chosenBranch)) { var developOrMainConfig = ChooseMainOrDevelopIncrementStrategyIfTheChosenBranchIsOneOfThem( chosenBranch, branchConfiguration, configuration); if (developOrMainConfig != null) { return(developOrMainConfig); } log.Warning("Fallback branch wants to inherit Increment branch configuration from itself. Using patch increment instead."); return(new BranchConfig(branchConfiguration) { Increment = IncrementStrategy.Patch }); } var inheritingBranchConfig = GetBranchConfiguration(chosenBranch, currentCommit, configuration, excludedInheritBranches); var configIncrement = inheritingBranchConfig.Increment; if (inheritingBranchConfig.Name.IsEquivalentTo(FallbackConfigName) && configIncrement == IncrementStrategy.Inherit) { log.Warning("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 }); } }