public static KeyValuePair<string, BranchConfig> GetBranchConfiguration(Commit currentCommit, IRepository repository, bool onlyEvaluateTrackedBranches, Config config, Branch currentBranch, IList<Branch> excludedInheritBranches = null)
        {
            var matchingBranches = LookupBranchConfiguration(config, currentBranch);

            if (matchingBranches.Length == 0)
            {
                var branchConfig = new BranchConfig();
                ConfigurationProvider.ApplyBranchDefaults(config, branchConfig);
                return new KeyValuePair<string, BranchConfig>(string.Empty, branchConfig);
            }
            if (matchingBranches.Length == 1)
            {
                var keyValuePair = matchingBranches[0];
                var branchConfiguration = keyValuePair.Value;

                if (branchConfiguration.Increment == IncrementStrategy.Inherit)
                {
                    return InheritBranchConfiguration(onlyEvaluateTrackedBranches, repository, currentCommit, currentBranch, keyValuePair, branchConfiguration, config, excludedInheritBranches);
                }

                return keyValuePair;
            }

            const string format = "Multiple branch configurations match the current branch branchName of '{0}'. Matching configurations: '{1}'";
            throw new Exception(string.Format(format, currentBranch.Name, string.Join(", ", matchingBranches.Select(b => b.Key))));
        }
        /// <summary>
        /// Gets the <see cref="BranchConfig"/> for the current commit.
        /// </summary>
        public static BranchConfig GetBranchConfiguration(GitVersionContext context, Branch targetBranch, IList<Branch> excludedInheritBranches = null)
        {
            var matchingBranches = LookupBranchConfiguration(context.FullConfiguration, targetBranch).ToArray();

            BranchConfig branchConfiguration;
            if (matchingBranches.Length > 0)
            {
                branchConfiguration = matchingBranches[0];

                if (matchingBranches.Length > 1)
                {
                    Logger.WriteWarning(string.Format(
                        "Multiple branch configurations match the current branch branchName of '{0}'. Using the first matching configuration, '{1}'. Matching configurations include: '{2}'",
                        targetBranch.FriendlyName,
                        branchConfiguration.Name,
                        string.Join("', '", matchingBranches.Select(b => b.Name))));
                }
            }
            else
            {
                Logger.WriteInfo(string.Format(
                    "No branch configuration found for branch {0}, falling back to default configuration",
                    targetBranch.FriendlyName));

                branchConfiguration = new BranchConfig { Name = string.Empty };
                ConfigurationProvider.ApplyBranchDefaults(context.FullConfiguration, branchConfiguration, "");
            }

            return branchConfiguration.Increment == IncrementStrategy.Inherit ?
                InheritBranchConfiguration(context, targetBranch, branchConfiguration, excludedInheritBranches) :
                branchConfiguration;
        }
Example #3
0
 public BranchConfig(BranchConfig branchConfiguration)
 {
     VersioningMode = branchConfiguration.VersioningMode;
     Tag = branchConfiguration.Tag;
     Increment = branchConfiguration.Increment;
     PreventIncrementOfMergedBranchVersion = branchConfiguration.PreventIncrementOfMergedBranchVersion;
     TagNumberPattern = branchConfiguration.TagNumberPattern;
     TrackMergeTarget = branchConfiguration.TrackMergeTarget;
 }
Example #4
0
 public BranchConfig(BranchConfig branchConfiguration)
 {
     VersioningMode = branchConfiguration.VersioningMode;
     Tag = branchConfiguration.Tag;
     Increment = branchConfiguration.Increment;
     PreventIncrementOfMergedBranchVersion = branchConfiguration.PreventIncrementOfMergedBranchVersion;
     TagNumberPattern = branchConfiguration.TagNumberPattern;
     TrackMergeTarget = branchConfiguration.TrackMergeTarget;
     CommitMessageIncrementing = branchConfiguration.CommitMessageIncrementing;
     DisableMergeMessageStrategy = branchConfiguration.DisableMergeMessageStrategy;
 }
Example #5
0
 public BranchConfig(BranchConfig branchConfiguration)
 {
     VersioningMode = branchConfiguration.VersioningMode;
     Tag = branchConfiguration.Tag;
     Increment = branchConfiguration.Increment;
     PreventIncrementOfMergedBranchVersion = branchConfiguration.PreventIncrementOfMergedBranchVersion;
     TagNumberPattern = branchConfiguration.TagNumberPattern;
     TrackMergeTarget = branchConfiguration.TrackMergeTarget;
     CommitMessageIncrementing = branchConfiguration.CommitMessageIncrementing;
     IsDevelop = branchConfiguration.IsDevelop;
     IsReleaseBranch = branchConfiguration.IsReleaseBranch;
 }
Example #6
0
 /// <summary>
 /// Creates a clone of the given <paramref name="branchConfiguration"/>.
 /// </summary>
 public BranchConfig(BranchConfig branchConfiguration)
 {
     VersioningMode = branchConfiguration.VersioningMode;
     Tag = branchConfiguration.Tag;
     Increment = branchConfiguration.Increment;
     PreventIncrementOfMergedBranchVersion = branchConfiguration.PreventIncrementOfMergedBranchVersion;
     TagNumberPattern = branchConfiguration.TagNumberPattern;
     TrackMergeTarget = branchConfiguration.TrackMergeTarget;
     CommitMessageIncrementing = branchConfiguration.CommitMessageIncrementing;
     TracksReleaseBranches = branchConfiguration.TracksReleaseBranches;
     Regex = branchConfiguration.Regex;
     IsReleaseBranch = branchConfiguration.IsReleaseBranch;
     IsMainline = branchConfiguration.IsMainline;
     Name = branchConfiguration.Name;
 }
 public static void ApplyBranchDefaults(Config config,
     BranchConfig branchConfig,
     string defaultTag = "useBranchName",
     IncrementStrategy defaultIncrementStrategy = IncrementStrategy.Patch,
     bool defaultPreventIncrement = false,
     VersioningMode? defaultVersioningMode = null, // Looked up from main config
     bool defaultTrackMergeTarget = false,
     string defaultTagNumberPattern = null)
 {
     branchConfig.Tag = branchConfig.Tag ?? defaultTag;
     branchConfig.TagNumberPattern = branchConfig.TagNumberPattern ?? defaultTagNumberPattern;
     branchConfig.Increment = branchConfig.Increment ?? defaultIncrementStrategy;
     branchConfig.PreventIncrementOfMergedBranchVersion = branchConfig.PreventIncrementOfMergedBranchVersion ?? defaultPreventIncrement;
     branchConfig.TrackMergeTarget = branchConfig.TrackMergeTarget ?? defaultTrackMergeTarget;
     branchConfig.VersioningMode = branchConfig.VersioningMode ?? defaultVersioningMode ?? config.VersioningMode;
 }
 public static void ApplyBranchDefaults(Config config,
     BranchConfig branchConfig,
     string branchRegex,
     string defaultTag = "useBranchName",
     IncrementStrategy? defaultIncrementStrategy = null, // Looked up from main config
     bool defaultPreventIncrement = false,
     VersioningMode? defaultVersioningMode = null, // Looked up from main config
     bool defaultTrackMergeTarget = false,
     string defaultTagNumberPattern = null,
     bool tracksReleaseBranches = false,
     bool isReleaseBranch = false,
     bool isMainline = false)
 {
     branchConfig.Regex = string.IsNullOrEmpty(branchConfig.Regex) ? branchRegex : branchConfig.Regex;
     branchConfig.Tag = branchConfig.Tag ?? defaultTag;
     branchConfig.TagNumberPattern = branchConfig.TagNumberPattern ?? defaultTagNumberPattern;
     branchConfig.Increment = branchConfig.Increment ?? defaultIncrementStrategy ?? config.Increment ?? DefaultIncrementStrategy;
     branchConfig.PreventIncrementOfMergedBranchVersion = branchConfig.PreventIncrementOfMergedBranchVersion ?? defaultPreventIncrement;
     branchConfig.TrackMergeTarget = branchConfig.TrackMergeTarget ?? defaultTrackMergeTarget;
     branchConfig.VersioningMode = branchConfig.VersioningMode ?? defaultVersioningMode ?? config.VersioningMode;
     branchConfig.TracksReleaseBranches = branchConfig.TracksReleaseBranches ?? tracksReleaseBranches;
     branchConfig.IsReleaseBranch = branchConfig.IsReleaseBranch ?? isReleaseBranch;
     branchConfig.IsMainline = branchConfig.IsMainline ?? isMainline;
 }
        static BranchConfig GetOrCreateBranchDefaults(Config config, string branch)
        {
            if (!config.Branches.ContainsKey(branch))
            {
                var branchConfig = new BranchConfig();
                config.Branches.Add(branch, branchConfig);
                return branchConfig;
            }

            return config.Branches[branch];
        }
Example #10
0
 public SetBranchTag(string name, BranchConfig branchConfig)
 {
     this.name         = name;
     this.branchConfig = branchConfig;
 }
        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 = LookupBranchConfiguration(config, b).ToArray();

                        // NOTE: if length is 0 we couldn't find the configuration for the branch e.g. "origin/master"
                        // NOTE: if the length is greater than 1 we cannot decide which merge strategy to pick
                        return((branchConfig.Length != 1) || (branchConfig.Length == 1 && branchConfig[0].Increment == IncrementStrategy.Inherit));
                    }).ToList();
                }
                // Add new excluded branches.
                foreach (var excludedBranch in excludedBranches.ExcludingBranches(excludedInheritBranches))
                {
                    excludedInheritBranches.Add(excludedBranch);
                }
                var branchesToEvaluate = repository.Branches.Except(excludedInheritBranches).ToList();

                var branchPoint = context.RepositoryMetadataProvider
                                  .FindCommitBranchWasBranchedFrom(targetBranch, excludedInheritBranches.ToArray());
                List <Branch> possibleParents;
                if (branchPoint == BranchCommit.Empty)
                {
                    possibleParents = context.RepositoryMetadataProvider.GetBranchesContainingCommit(context.CurrentCommit, 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);
                    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 chosenBranch = repository.Branches.FirstOrDefault(b => Regex.IsMatch(b.FriendlyName, "^develop", RegexOptions.IgnoreCase) ||
                                                                      Regex.IsMatch(b.FriendlyName, "master$", 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))
                {
                    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);
                return(new BranchConfig(branchConfiguration)
                {
                    Increment = inheritingBranchConfig.Increment,
                    PreventIncrementOfMergedBranchVersion = inheritingBranchConfig.PreventIncrementOfMergedBranchVersion,
                    // If we are inheriting from develop then we should behave like develop
                    TracksReleaseBranches = inheritingBranchConfig.TracksReleaseBranches
                });
            }
        }
        static KeyValuePair<string, BranchConfig> InheritBranchConfiguration(bool onlyEvaluateTrackedBranches, IRepository repository, Commit currentCommit, Branch currentBranch, KeyValuePair<string, BranchConfig> keyValuePair, BranchConfig branchConfiguration, Config config, IList<Branch> excludedInheritBranches)
        {
            using (Logger.IndentLog("Attempting to inherit branch configuration from parent branch"))
            {
                var excludedBranches = new[] { currentBranch };
                // Check if we are a merge commit. If so likely we are a pull request
                var parentCount = currentCommit.Parents.Count();
                if (parentCount == 2)
                {
                    var parents = currentCommit.Parents.ToArray();
                    var branch = repository.Branches.SingleOrDefault(b => !b.IsRemote && b.Tip == parents[1]);
                    if (branch != null)
                    {
                        excludedBranches = new[]
                        {
                        currentBranch,
                        branch
                    };
                        currentBranch = branch;
                    }
                    else
                    {
                        var possibleTargetBranches = repository.Branches.Where(b => !b.IsRemote && b.Tip == parents[0]).ToList();
                        if (possibleTargetBranches.Count() > 1)
                        {
                            currentBranch = possibleTargetBranches.FirstOrDefault(b => b.Name == "master") ?? possibleTargetBranches.First();
                        }
                        else
                        {
                            currentBranch = possibleTargetBranches.FirstOrDefault() ?? currentBranch;
                        }
                    }

                    Logger.WriteInfo("HEAD is merge commit, this is likely a pull request using " + currentBranch.Name + " as base");
                }
                if (excludedInheritBranches == null)
                {
                    excludedInheritBranches = repository.Branches.Where(b =>
                    {
                        var branchConfig = LookupBranchConfiguration(config, b);
                        return branchConfig.Length == 1 && branchConfig[0].Value.Increment == IncrementStrategy.Inherit;
                    }).ToList();
                }
                excludedBranches.ToList().ForEach(excludedInheritBranches.Add);

                var branchPoint = currentBranch.FindCommitBranchWasBranchedFrom(repository, excludedInheritBranches.ToArray());

                List<Branch> possibleParents;
                if (branchPoint == null)
                {
                    possibleParents = currentCommit.GetBranchesContainingCommit(repository, true).Except(excludedInheritBranches).ToList();
                }
                else
                {
                    var branches = branchPoint.GetBranchesContainingCommit(repository, true).Except(excludedInheritBranches).ToList();
                    if (branches.Count > 1)
                    {
                        var currentTipBranches = currentCommit.GetBranchesContainingCommit(repository, true).Except(excludedInheritBranches).ToList();
                        possibleParents = branches.Except(currentTipBranches).ToList();
                    }
                    else
                    {
                        possibleParents = branches;
                    }
                }

                Logger.WriteInfo("Found possible parent branches: " + string.Join(", ", possibleParents.Select(p => p.Name)));

                if (possibleParents.Count == 1)
                {
                    var branchConfig = GetBranchConfiguration(currentCommit, repository, onlyEvaluateTrackedBranches, config, possibleParents[0], excludedInheritBranches).Value;
                    return new KeyValuePair<string, BranchConfig>(
                        keyValuePair.Key,
                        new BranchConfig(branchConfiguration)
                        {
                            Increment = branchConfig.Increment,
                            PreventIncrementOfMergedBranchVersion = branchConfig.PreventIncrementOfMergedBranchVersion
                        });
                }

                // 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.Name));

                var developBranch = repository.Branches.FirstOrDefault(b => Regex.IsMatch(b.Name, "^develop", RegexOptions.IgnoreCase));
                var branchName = developBranch != null ? developBranch.Name : "master";

                Logger.WriteWarning(errorMessage + Environment.NewLine + Environment.NewLine + "Falling back to " + branchName + " branch config");
                var value = GetBranchConfiguration(currentCommit, repository, onlyEvaluateTrackedBranches, config, repository.Branches[branchName]).Value;
                return new KeyValuePair<string, BranchConfig>(
                    keyValuePair.Key,
                    new BranchConfig(branchConfiguration)
                    {
                        Increment = value.Increment,
                        PreventIncrementOfMergedBranchVersion = value.PreventIncrementOfMergedBranchVersion
                    });
            }
        }
        static BranchConfig GetOrCreateBranchDefaults(Config config, string branchKey)
        {
            if (!config.Branches.ContainsKey(branchKey))
            {
                var branchConfig = new BranchConfig {Name = branchKey};
                config.Branches.Add(branchKey, branchConfig);
                return branchConfig;
            }

            return config.Branches[branchKey];
        }
        static KeyValuePair <string, BranchConfig> InheritBranchConfiguration(bool onlyEvaluateTrackedBranches, IRepository repository, Commit currentCommit, Branch currentBranch, KeyValuePair <string, BranchConfig> keyValuePair, BranchConfig branchConfiguration, Config config, IList <Branch> excludedInheritBranches)
        {
            Logger.WriteInfo("Attempting to inherit branch configuration from parent branch");
            var excludedBranches = new [] { currentBranch };
            // Check if we are a merge commit. If so likely we are a pull request
            var parentCount = currentCommit.Parents.Count();

            if (parentCount == 2)
            {
                var parents = currentCommit.Parents.ToArray();
                var branch  = repository.Branches.SingleOrDefault(b => !b.IsRemote && b.Tip == parents[1]);
                if (branch != null)
                {
                    excludedBranches = new[]
                    {
                        currentBranch,
                        branch
                    };
                    currentBranch = branch;
                }
                else
                {
                    var possibleTargetBranches = repository.Branches.Where(b => !b.IsRemote && b.Tip == parents[0]).ToList();
                    if (possibleTargetBranches.Count() > 1)
                    {
                        currentBranch = possibleTargetBranches.FirstOrDefault(b => b.Name == "master") ?? possibleTargetBranches.First();
                    }
                    else
                    {
                        currentBranch = possibleTargetBranches.FirstOrDefault() ?? currentBranch;
                    }
                }

                Logger.WriteInfo("HEAD is merge commit, this is likely a pull request using " + currentBranch.Name + " as base");
            }
            if (excludedInheritBranches == null)
            {
                excludedInheritBranches = repository.Branches.Where(b =>
                {
                    var branchConfig = LookupBranchConfiguration(config, b);
                    return(branchConfig.Length == 1 && branchConfig[0].Value.Increment == IncrementStrategy.Inherit);
                }).ToList();
            }
            excludedBranches.ToList().ForEach(excludedInheritBranches.Add);

            var branchPoint = currentBranch.FindCommitBranchWasBranchedFrom(repository, excludedInheritBranches.ToArray());

            List <Branch> possibleParents;

            if (branchPoint == null)
            {
                possibleParents = currentCommit.GetBranchesContainingCommit(repository, true).Except(excludedInheritBranches).ToList();
            }
            else
            {
                var branches = branchPoint.GetBranchesContainingCommit(repository, true).Except(excludedInheritBranches).ToList();
                if (branches.Count > 1)
                {
                    var currentTipBranches = currentCommit.GetBranchesContainingCommit(repository, true).Except(excludedInheritBranches).ToList();
                    possibleParents = branches.Except(currentTipBranches).ToList();
                }
                else
                {
                    possibleParents = branches;
                }
            }

            Logger.WriteInfo("Found possible parent branches: " + string.Join(", ", possibleParents.Select(p => p.Name)));

            if (possibleParents.Count == 1)
            {
                var branchConfig = GetBranchConfiguration(currentCommit, repository, onlyEvaluateTrackedBranches, config, possibleParents[0], excludedInheritBranches).Value;
                return(new KeyValuePair <string, BranchConfig>(
                           keyValuePair.Key,
                           new BranchConfig(branchConfiguration)
                {
                    Increment = branchConfig.Increment,
                    PreventIncrementOfMergedBranchVersion = branchConfig.PreventIncrementOfMergedBranchVersion
                }));
            }

            // 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.Name));
            }

            var developBranch = repository.Branches.FirstOrDefault(b => Regex.IsMatch(b.Name, "^develop", RegexOptions.IgnoreCase));
            var branchName    = developBranch != null ? developBranch.Name : "master";

            Logger.WriteWarning(errorMessage + Environment.NewLine + Environment.NewLine + "Falling back to " + branchName + " branch config");
            var value = GetBranchConfiguration(currentCommit, repository, onlyEvaluateTrackedBranches, config, repository.Branches[branchName]).Value;

            return(new KeyValuePair <string, BranchConfig>(
                       keyValuePair.Key,
                       new BranchConfig(branchConfiguration)
            {
                Increment = value.Increment,
                PreventIncrementOfMergedBranchVersion = value.PreventIncrementOfMergedBranchVersion
            }));
        }
        static KeyValuePair<string, BranchConfig> InheritBranchConfiguration(
            bool onlyEvaluateTrackedBranches, IRepository repository, Commit currentCommit,
            Branch currentBranch, KeyValuePair<string, BranchConfig> keyValuePair,
            BranchConfig branchConfiguration, Config config)
        {
            Logger.WriteInfo("Attempting to inherit branch configuration from parent branch");
            var excludedBranches = new [] { currentBranch };
            // Check if we are a merge commit. If so likely we are a pull request
            var parentCount = currentCommit.Parents.Count();
            if (parentCount == 2)
            {
                var parents = currentCommit.Parents.ToArray();
                var branch = repository.Branches.SingleOrDefault(b => !b.IsRemote && b.Tip == parents[1]);
                if (branch != null)
                {
                    excludedBranches = new[]
                    {
                        currentBranch,
                        branch
                    };
                    currentBranch = branch;
                }
                else
                {
                    currentBranch = repository.Branches.SingleOrDefault(b => !b.IsRemote && b.Tip == parents[0]) ?? currentBranch;
                }

                Logger.WriteInfo("HEAD is merge commit, this is likely a pull request using " + currentBranch.Name + " as base");
            }

            var branchPoint = currentBranch.FindCommitBranchWasBranchedFrom(repository, onlyEvaluateTrackedBranches, excludedBranches);

            List<Branch> possibleParents;
            if (branchPoint.Sha == currentCommit.Sha)
            {
                possibleParents = currentCommit.GetBranchesContainingCommit(repository, true).Except(excludedBranches).ToList();
            }
            else
            {
                var branches = branchPoint.GetBranchesContainingCommit(repository, true).Except(excludedBranches).ToList();
                var currentTipBranches = currentCommit.GetBranchesContainingCommit(repository, true).Except(excludedBranches).ToList();
                possibleParents = branches
                    .Except(currentTipBranches)
                    .ToList();
            }

            Logger.WriteInfo("Found possible parent branches: " + string.Join(", ", possibleParents.Select(p => p.Name)));

            // If it comes down to master and something, master is always first so we pick other branch
            if (possibleParents.Count == 2 && possibleParents.Any(p => p.Name == "master"))
            {
                possibleParents.Remove(possibleParents.Single(p => p.Name == "master"));
            }

            if (possibleParents.Count == 1)
            {
                var branchConfig = GetBranchConfiguration(currentCommit, repository, onlyEvaluateTrackedBranches, config, possibleParents[0]).Value;
                return new KeyValuePair<string, BranchConfig>(
                    keyValuePair.Key,
                    new BranchConfig(branchConfiguration)
                    {
                        Increment = branchConfig.Increment,
                        PreventIncrementOfMergedBranchVersion = branchConfig.PreventIncrementOfMergedBranchVersion
                    });
            }

            // 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.Name));

            var hasDevelop = repository.FindBranch("develop") != null;
            var branchName = hasDevelop ? "develop" : "master";

            Logger.WriteWarning(errorMessage + Environment.NewLine + Environment.NewLine + "Falling back to " + branchName + " branch config");
            var value = GetBranchConfiguration(currentCommit, repository, onlyEvaluateTrackedBranches, config, repository.Branches[branchName]).Value;
            return new KeyValuePair<string, BranchConfig>(
                keyValuePair.Key,
                new BranchConfig(branchConfiguration)
                {
                    Increment = value.Increment,
                    PreventIncrementOfMergedBranchVersion = value.PreventIncrementOfMergedBranchVersion
                });
        }
Example #16
0
 public ConfigureBranch(string name, BranchConfig branchConfig)
 {
     this.branchConfig = branchConfig;
     this.name         = name;
 }
Example #17
0
        static KeyValuePair <string, BranchConfig> InheritBranchConfiguration(bool onlyEvaluateTrackedBranches, IRepository repository, Commit currentCommit, Branch currentBranch, KeyValuePair <string, BranchConfig> keyValuePair, BranchConfig branchConfiguration, Config config, IList <Branch> excludedInheritBranches)
        {
            using (Logger.IndentLog("Attempting to inherit branch configuration from parent branch"))
            {
                var excludedBranches = new[] { currentBranch };
                // 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(repository, currentCommit, ref currentBranch, excludedBranches);
                }

                if (excludedInheritBranches == null)
                {
                    excludedInheritBranches = repository.Branches.Where(b =>
                    {
                        var branchConfig = LookupBranchConfiguration(config, b);

                        // NOTE: if length is 0 we couldn't find the configuration for the branch e.g. "origin/master"
                        // NOTE: if the length is greater than 1 we cannot decide which merge strategy to pick
                        return((branchConfig.Length != 1) || (branchConfig.Length == 1 && branchConfig[0].Value.Increment == IncrementStrategy.Inherit));
                    }).ToList();
                }
                excludedBranches.ToList().ForEach(excludedInheritBranches.Add);
                var branchesToEvaluate = repository.Branches.Except(excludedInheritBranches).ToList();

                var           branchPoint = currentBranch.FindCommitBranchWasBranchedFrom(repository, excludedInheritBranches.ToArray());
                List <Branch> possibleParents;
                if (branchPoint == null)
                {
                    possibleParents = currentCommit.GetBranchesContainingCommit(repository, branchesToEvaluate, true).ToList();
                }
                else
                {
                    var branches = branchPoint.GetBranchesContainingCommit(repository, branchesToEvaluate, true).ToList();
                    if (branches.Count > 1)
                    {
                        var currentTipBranches = currentCommit.GetBranchesContainingCommit(repository, branchesToEvaluate, true).ToList();
                        possibleParents = branches.Except(currentTipBranches).ToList();
                    }
                    else
                    {
                        possibleParents = branches;
                    }
                }

                Logger.WriteInfo("Found possible parent branches: " + string.Join(", ", possibleParents.Select(p => p.Name)));

                if (possibleParents.Count == 1)
                {
                    var branchConfig = GetBranchConfiguration(currentCommit, repository, onlyEvaluateTrackedBranches, config, possibleParents[0], excludedInheritBranches).Value;
                    return(new KeyValuePair <string, BranchConfig>(
                               keyValuePair.Key,
                               new BranchConfig(branchConfiguration)
                    {
                        Increment = branchConfig.Increment,
                        PreventIncrementOfMergedBranchVersion = branchConfig.PreventIncrementOfMergedBranchVersion
                    }));
                }

                // 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.Name));
                }

                var chosenBranch = repository.Branches.FirstOrDefault(b => Regex.IsMatch(b.Name, "^develop", RegexOptions.IgnoreCase) ||
                                                                      Regex.IsMatch(b.Name, "master$", RegexOptions.IgnoreCase));
                if (chosenBranch == null)
                {
                    throw new InvalidOperationException("Could not find a 'develop' or 'master' branch, neither locally nor remotely.");
                }

                var branchName = chosenBranch.Name;
                Logger.WriteWarning(errorMessage + Environment.NewLine + Environment.NewLine + "Falling back to " + branchName + " branch config");

                var value = GetBranchConfiguration(currentCommit, repository, onlyEvaluateTrackedBranches, config, chosenBranch).Value;
                return(new KeyValuePair <string, BranchConfig>(
                           keyValuePair.Key,
                           new BranchConfig(branchConfiguration)
                {
                    Increment = value.Increment,
                    PreventIncrementOfMergedBranchVersion = value.PreventIncrementOfMergedBranchVersion
                }));
            }
        }
        static KeyValuePair <string, BranchConfig> InheritBranchConfiguration(
            bool onlyEvaluateTrackedBranches, IRepository repository, Commit currentCommit,
            Branch currentBranch, KeyValuePair <string, BranchConfig> keyValuePair,
            BranchConfig branchConfiguration, Config config)
        {
            Logger.WriteInfo("Attempting to inherit branch configuration from parent branch");
            var excludedBranches = new [] { currentBranch };
            // Check if we are a merge commit. If so likely we are a pull request
            var parentCount = currentCommit.Parents.Count();

            if (parentCount == 2)
            {
                var parents = currentCommit.Parents.ToArray();
                var branch  = repository.Branches.SingleOrDefault(b => !b.IsRemote && b.Tip == parents[1]);
                if (branch != null)
                {
                    excludedBranches = new[]
                    {
                        currentBranch,
                        branch
                    };
                    currentBranch = branch;
                }
                else
                {
                    currentBranch = repository.Branches.SingleOrDefault(b => !b.IsRemote && b.Tip == parents[0]) ?? currentBranch;
                }

                Logger.WriteInfo("HEAD is merge commit, this is likely a pull request using " + currentBranch.Name + " as base");
            }

            var branchPoint = currentBranch.FindCommitBranchWasBranchedFrom(repository, onlyEvaluateTrackedBranches, excludedBranches);

            List <Branch> possibleParents;

            if (branchPoint.Sha == currentCommit.Sha)
            {
                possibleParents = currentCommit.GetBranchesContainingCommit(repository, true).Except(excludedBranches).ToList();
            }
            else
            {
                var branches           = branchPoint.GetBranchesContainingCommit(repository, true).Except(excludedBranches).ToList();
                var currentTipBranches = currentCommit.GetBranchesContainingCommit(repository, true).Except(excludedBranches).ToList();
                possibleParents = branches
                                  .Except(currentTipBranches)
                                  .ToList();
            }

            Logger.WriteInfo("Found possible parent branches: " + string.Join(", ", possibleParents.Select(p => p.Name)));

            // If it comes down to master and something, master is always first so we pick other branch
            if (possibleParents.Count == 2 && possibleParents.Any(p => p.Name == "master"))
            {
                possibleParents.Remove(possibleParents.Single(p => p.Name == "master"));
            }

            if (possibleParents.Count == 1)
            {
                var branchConfig = GetBranchConfiguration(currentCommit, repository, onlyEvaluateTrackedBranches, config, possibleParents[0]).Value;
                return(new KeyValuePair <string, BranchConfig>(
                           keyValuePair.Key,
                           new BranchConfig(branchConfiguration)
                {
                    Increment = branchConfig.Increment,
                    PreventIncrementOfMergedBranchVersion = branchConfig.PreventIncrementOfMergedBranchVersion
                }));
            }

            // 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.Name));
            }

            var hasDevelop = repository.FindBranch("develop") != null;
            var branchName = hasDevelop ? "develop" : "master";

            Logger.WriteWarning(errorMessage + Environment.NewLine + Environment.NewLine + "Falling back to " + branchName + " branch config");
            var value = GetBranchConfiguration(currentCommit, repository, onlyEvaluateTrackedBranches, config, repository.Branches[branchName]).Value;

            return(new KeyValuePair <string, BranchConfig>(
                       keyValuePair.Key,
                       new BranchConfig(branchConfiguration)
            {
                Increment = value.Increment,
                PreventIncrementOfMergedBranchVersion = value.PreventIncrementOfMergedBranchVersion
            }));
        }
        static KeyValuePair<string, BranchConfig> InheritBranchConfiguration(bool onlyEvaluateTrackedBranches, IRepository repository, Commit currentCommit, Branch currentBranch, KeyValuePair<string, BranchConfig> keyValuePair, BranchConfig branchConfiguration, Config config, IList<Branch> excludedInheritBranches)
        {
            using (Logger.IndentLog("Attempting to inherit branch configuration from parent branch"))
            {
                var excludedBranches = new[] { currentBranch };
                // 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(repository, currentCommit, ref currentBranch, excludedBranches);
                }

                if (excludedInheritBranches == null)
                {
                    excludedInheritBranches = repository.Branches.Where(b =>
                    {
                        var branchConfig = LookupBranchConfiguration(config, b);

                        // NOTE: if length is 0 we couldn't find the configuration for the branch e.g. "origin/master"
                        // NOTE: if the length is greater than 1 we cannot decide which merge strategy to pick
                        return (branchConfig.Length != 1) || (branchConfig.Length == 1 && branchConfig[0].Value.Increment == IncrementStrategy.Inherit);
                    }).ToList();
                }
                excludedBranches.ToList().ForEach(excludedInheritBranches.Add);
                var branchesToEvaluate = repository.Branches.Except(excludedInheritBranches).ToList();

                var branchPoint = currentBranch.FindCommitBranchWasBranchedFrom(repository, excludedInheritBranches.ToArray());
                List<Branch> possibleParents;
                if (branchPoint == null)
                {
                    possibleParents = currentCommit.GetBranchesContainingCommit(repository, branchesToEvaluate, true).ToList();
                }
                else
                {
                    var branches = branchPoint.GetBranchesContainingCommit(repository, branchesToEvaluate, true).ToList();
                    if (branches.Count > 1)
                    {
                        var currentTipBranches = currentCommit.GetBranchesContainingCommit(repository, branchesToEvaluate, true).ToList();
                        possibleParents = branches.Except(currentTipBranches).ToList();
                    }
                    else
                    {
                        possibleParents = branches;
                    }
                }

                Logger.WriteInfo("Found possible parent branches: " + string.Join(", ", possibleParents.Select(p => p.Name)));

                if (possibleParents.Count == 1)
                {
                    var branchConfig = GetBranchConfiguration(currentCommit, repository, onlyEvaluateTrackedBranches, config, possibleParents[0], excludedInheritBranches).Value;
                    return new KeyValuePair<string, BranchConfig>(
                        keyValuePair.Key,
                        new BranchConfig(branchConfiguration)
                        {
                            Increment = branchConfig.Increment,
                            PreventIncrementOfMergedBranchVersion = branchConfig.PreventIncrementOfMergedBranchVersion
                        });
                }

                // 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.Name));

                var chosenBranch = repository.Branches.FirstOrDefault(b => Regex.IsMatch(b.Name, "^develop", RegexOptions.IgnoreCase)
                                                                           || Regex.IsMatch(b.Name, "master$", RegexOptions.IgnoreCase));
                if (chosenBranch == null)
                    throw new InvalidOperationException("Could not find a 'develop' or 'master' branch, neither locally nor remotely.");

                var branchName = chosenBranch.Name;
                Logger.WriteWarning(errorMessage + Environment.NewLine + Environment.NewLine + "Falling back to " + branchName + " branch config");

                var value = GetBranchConfiguration(currentCommit, repository, onlyEvaluateTrackedBranches, config, chosenBranch).Value;
                return new KeyValuePair<string, BranchConfig>(
                    keyValuePair.Key,
                    new BranchConfig(branchConfiguration)
                    {
                        Increment = value.Increment,
                        PreventIncrementOfMergedBranchVersion = value.PreventIncrementOfMergedBranchVersion
                    });
            }
        }
        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 = LookupBranchConfiguration(config, b).ToArray();

                        // NOTE: if length is 0 we couldn't find the configuration for the branch e.g. "origin/master"
                        // NOTE: if the length is greater than 1 we cannot decide which merge strategy to pick
                        return (branchConfig.Length != 1) || (branchConfig.Length == 1 && branchConfig[0].Increment == IncrementStrategy.Inherit);
                    }).ToList();
                }
                // Add new excluded branches.
                foreach (var excludedBranch in excludedBranches.ExcludingBranches(excludedInheritBranches))
                {
                    excludedInheritBranches.Add(excludedBranch);
                }
                var branchesToEvaluate = repository.Branches.Except(excludedInheritBranches).ToList();

                var branchPoint = context.RepositoryMetadataProvider
                    .FindCommitBranchWasBranchedFrom(targetBranch, excludedInheritBranches.ToArray());
                List<Branch> possibleParents;
                if (branchPoint == BranchCommit.Empty)
                {
                    possibleParents = context.RepositoryMetadataProvider.GetBranchesContainingCommit(context.CurrentCommit, 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);
                    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 chosenBranch = repository.Branches.FirstOrDefault(b => Regex.IsMatch(b.FriendlyName, "^develop", RegexOptions.IgnoreCase)
                                                                           || Regex.IsMatch(b.FriendlyName, "master$", 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))
                {
                    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);
                return new BranchConfig(branchConfiguration)
                {
                    Increment = inheritingBranchConfig.Increment,
                    PreventIncrementOfMergedBranchVersion = inheritingBranchConfig.PreventIncrementOfMergedBranchVersion,
                    // If we are inheriting from develop then we should behave like develop
                    TracksReleaseBranches = inheritingBranchConfig.TracksReleaseBranches
                };
            }
        }