diff --git a/src/GitVersion.App/ArgumentParser.cs b/src/GitVersion.App/ArgumentParser.cs index f22b06f7b9..0e569d9106 100644 --- a/src/GitVersion.App/ArgumentParser.cs +++ b/src/GitVersion.App/ArgumentParser.cs @@ -248,9 +248,8 @@ private static bool ParseSwitches(Arguments arguments, string? name, IReadOnlyLi return true; } - if (name.IsSwitch("diag")) + if (ParseBooleanArguments(arguments, name)) { - arguments.Diag = true; return true; } @@ -297,6 +296,23 @@ private static bool ParseSwitches(Arguments arguments, string? name, IReadOnlyLi return true; } + if (!name.IsSwitch("verbosity")) + { + return false; + } + + arguments.Verbosity = ParseVerbosity(value); + return true; + } + + private static bool ParseBooleanArguments(Arguments arguments, string? name) + { + if (name.IsSwitch("diag")) + { + arguments.Diag = true; + return true; + } + if (name.IsSwitch("nofetch")) { arguments.NoFetch = true; @@ -321,12 +337,6 @@ private static bool ParseSwitches(Arguments arguments, string? name, IReadOnlyLi return true; } - if (name.IsSwitch("verbosity")) - { - arguments.Verbosity = ParseVerbosity(value); - return true; - } - if (!name.IsSwitch("updatewixversionfile")) { return false; diff --git a/src/GitVersion.Core/Core/GitPreparer.cs b/src/GitVersion.Core/Core/GitPreparer.cs index 9dcd4a34bb..f4d61b42b3 100644 --- a/src/GitVersion.Core/Core/GitPreparer.cs +++ b/src/GitVersion.Core/Core/GitPreparer.cs @@ -395,21 +395,8 @@ public void EnsureLocalBranchExistsForCurrentBranch(IRemote remote, string? curr return; } - const string referencePrefix = "refs/"; var isLocalBranch = currentBranch.StartsWith(ReferenceName.LocalBranchPrefix); - string localCanonicalName; - if (!currentBranch.StartsWith(referencePrefix)) - { - localCanonicalName = ReferenceName.LocalBranchPrefix + currentBranch; - } - else if (isLocalBranch) - { - localCanonicalName = currentBranch; - } - else - { - localCanonicalName = ReferenceName.LocalBranchPrefix + currentBranch[referencePrefix.Length..]; - } + var localCanonicalName = ResolveLocalCanonicalName(currentBranch, isLocalBranch); var repoTip = this.repository.Head.Tip; @@ -425,28 +412,49 @@ public void EnsureLocalBranchExistsForCurrentBranch(IRemote remote, string? curr if (repoTipId != null) { - var referenceName = ReferenceName.Parse(localCanonicalName); - if (this.repository.Branches.All(b => !b.Name.Equals(referenceName))) - { - this.log.Info(isLocalBranch - ? $"Creating local branch {referenceName}" - : $"Creating local branch {referenceName} pointing at {repoTipId}"); - this.repository.References.Add(localCanonicalName, repoTipId.Sha); - } - else - { - this.log.Info(isLocalBranch - ? $"Updating local branch {referenceName} to point at {repoTipId}" - : $"Updating local branch {referenceName} to match ref {currentBranch}"); - var localRef = this.repository.References[localCanonicalName]; - if (localRef != null) - { - this.retryAction.Execute(() => this.repository.References.UpdateTarget(localRef, repoTipId)); - } - } + CreateOrUpdateLocalBranch(localCanonicalName, repoTipId, isLocalBranch, currentBranch); } + Checkout(localCanonicalName); } + private static string ResolveLocalCanonicalName(string currentBranch, bool isLocalBranch) + { + const string referencePrefix = "refs/"; + if (!currentBranch.StartsWith(referencePrefix)) + { + return ReferenceName.LocalBranchPrefix + currentBranch; + } + + if (isLocalBranch) + { + return currentBranch; + } + + return ReferenceName.LocalBranchPrefix + currentBranch[referencePrefix.Length..]; + } + + private void CreateOrUpdateLocalBranch(string localCanonicalName, IObjectId repoTipId, bool isLocalBranch, string currentBranch) + { + var referenceName = ReferenceName.Parse(localCanonicalName); + if (this.repository.Branches.All(b => !b.Name.Equals(referenceName))) + { + this.log.Info(isLocalBranch + ? $"Creating local branch {referenceName}" + : $"Creating local branch {referenceName} pointing at {repoTipId}"); + this.repository.References.Add(localCanonicalName, repoTipId.Sha); + return; + } + + this.log.Info(isLocalBranch + ? $"Updating local branch {referenceName} to point at {repoTipId}" + : $"Updating local branch {referenceName} to match ref {currentBranch}"); + var localRef = this.repository.References[localCanonicalName]; + if (localRef != null) + { + this.retryAction.Execute(() => this.repository.References.UpdateTarget(localRef, repoTipId)); + } + } + private void Checkout(string commitOrBranchSpec) => this.retryAction.Execute(() => this.repository.Checkout(commitOrBranchSpec)); } diff --git a/src/GitVersion.Core/Core/RepositoryStore.cs b/src/GitVersion.Core/Core/RepositoryStore.cs index 8767ebf746..ac248efc6f 100644 --- a/src/GitVersion.Core/Core/RepositoryStore.cs +++ b/src/GitVersion.Core/Core/RepositoryStore.cs @@ -120,6 +120,21 @@ public IEnumerable GetSourceBranches( var commitBranches = FindCommitBranchesBranchedFrom(branch, configuration, excludedBranches).ToHashSet(); + var ignore = CollectIgnoredMergeCommitBranches(branch, commitBranches); + + RemoveCommitBranchesFoundInOtherBranches(commitBranches, ignore); + + foreach (var branchGrouping in commitBranches.GroupBy(element => element.Commit, element => element.Branch)) + { + foreach (var item in GetSourceBranchesForGrouping(branchGrouping, referenceLookup, returnedBranches)) + { + yield return item; + } + } + } + + private static HashSet CollectIgnoredMergeCommitBranches(IBranch branch, HashSet commitBranches) + { var ignore = new HashSet(); foreach (var commitBranch in commitBranches) { @@ -133,6 +148,11 @@ public IEnumerable GetSourceBranches( } } + return ignore; + } + + private static void RemoveCommitBranchesFoundInOtherBranches(HashSet commitBranches, HashSet ignore) + { foreach (var item in commitBranches.Skip(1).Reverse().Where(item => !ignore.Contains(item))) { foreach (var commitBranch in commitBranches) @@ -148,31 +168,32 @@ public IEnumerable GetSourceBranches( } } } + } - foreach (var branchGrouping in commitBranches.GroupBy(element => element.Commit, element => element.Branch)) - { - var referenceMatchFound = false; - var referenceNames = referenceLookup[branchGrouping.Key.Sha].Select(element => element.Name).ToHashSet(); + private static IEnumerable GetSourceBranchesForGrouping( + IGrouping branchGrouping, ILookup referenceLookup, HashSet returnedBranches) + { + var referenceMatchFound = false; + var referenceNames = referenceLookup[branchGrouping.Key.Sha].Select(element => element.Name).ToHashSet(); - foreach (var item in branchGrouping.Where(item => referenceNames.Contains(item.Name))) + foreach (var item in branchGrouping.Where(item => referenceNames.Contains(item.Name))) + { + if (returnedBranches.Add(item)) { - if (returnedBranches.Add(item)) - { - yield return item; - } - - referenceMatchFound = true; + yield return item; } - if (referenceMatchFound) - { - continue; - } + referenceMatchFound = true; + } - foreach (var item in branchGrouping.Where(returnedBranches.Add)) - { - yield return item; - } + if (referenceMatchFound) + { + yield break; + } + + foreach (var item in branchGrouping.Where(returnedBranches.Add)) + { + yield return item; } } diff --git a/src/GitVersion.Core/SemVer/SemanticVersion.cs b/src/GitVersion.Core/SemVer/SemanticVersion.cs index 5803e1251b..b8e2f04df9 100644 --- a/src/GitVersion.Core/SemVer/SemanticVersion.cs +++ b/src/GitVersion.Core/SemVer/SemanticVersion.cs @@ -362,76 +362,56 @@ public SemanticVersion Increment( public SemanticVersion Increment( VersionField increment, string? label, IncrementMode mode, params SemanticVersion?[] alternativeSemanticVersions) { - var major = Major; - var minor = Minor; - var patch = Patch; - var preReleaseNumber = PreReleaseTag.Number; - var hasPreReleaseTag = PreReleaseTag.HasTag(); - switch (increment) - { - case VersionField.None: - preReleaseNumber++; - break; + var (major, minor, patch, preReleaseNumber) = ApplyIncrement(increment, mode, hasPreReleaseTag); - case VersionField.Patch: - if (hasPreReleaseTag && (mode == IncrementMode.Standard - || (mode == IncrementMode.EnsureIntegrity && patch != 0))) - { - preReleaseNumber++; - } - else - { - patch++; - if (preReleaseNumber.HasValue) - { - preReleaseNumber = 1; - } - } - break; + var (semanticVersion, foundAlternativeSemanticVersion) = + SelectAlternativeIfGreater(new SemanticVersion(major, minor, patch), alternativeSemanticVersions); + major = semanticVersion.Major; + minor = semanticVersion.Minor; + patch = semanticVersion.Patch; - case VersionField.Minor: - if (hasPreReleaseTag && (mode == IncrementMode.Standard - || (mode == IncrementMode.EnsureIntegrity && minor != 0 && patch == 0))) - { - preReleaseNumber++; - } - else - { - minor++; - patch = 0; - if (preReleaseNumber.HasValue) - { - preReleaseNumber = 1; - } - } - break; + if (foundAlternativeSemanticVersion && increment == VersionField.None) + { + preReleaseNumber = 1; + } - case VersionField.Major: - if (hasPreReleaseTag && (mode == IncrementMode.Standard - || (mode == IncrementMode.EnsureIntegrity && major != 0 && minor == 0 && patch == 0))) - { - preReleaseNumber++; - } - else - { - major++; - minor = 0; - patch = 0; - if (preReleaseNumber.HasValue) - { - preReleaseNumber = 1; - } - } - break; + return BuildIncrementedVersion(major, minor, patch, preReleaseNumber, hasPreReleaseTag, label); + } - default: - throw new ArgumentOutOfRangeException(nameof(increment)); + private (long Major, long Minor, long Patch, long? PreReleaseNumber) ApplyIncrement( + VersionField increment, IncrementMode mode, bool hasPreReleaseTag) + { + var preReleaseNumber = PreReleaseTag.Number; + return increment switch + { + VersionField.None => (Major, Minor, Patch, preReleaseNumber + 1), + VersionField.Patch => IncrementField(mode, hasPreReleaseTag, Patch != 0, Major, Minor, Patch + 1, preReleaseNumber), + VersionField.Minor => IncrementField(mode, hasPreReleaseTag, Minor != 0 && Patch == 0, Major, Minor + 1, 0, preReleaseNumber), + VersionField.Major => IncrementField(mode, hasPreReleaseTag, Major != 0 && Minor == 0 && Patch == 0, Major + 1, 0, 0, preReleaseNumber), + _ => throw new ArgumentOutOfRangeException(nameof(increment)) + }; + } + + private (long Major, long Minor, long Patch, long? PreReleaseNumber) IncrementField( + IncrementMode mode, bool hasPreReleaseTag, bool integrityCondition, + long bumpedMajor, long bumpedMinor, long bumpedPatch, long? preReleaseNumber) + { + if (ShouldIncrementPreReleaseNumber(mode, hasPreReleaseTag, integrityCondition)) + { + return (Major, Minor, Patch, preReleaseNumber + 1); } - SemanticVersion semanticVersion = new(major, minor, patch); + return (bumpedMajor, bumpedMinor, bumpedPatch, preReleaseNumber.HasValue ? 1 : preReleaseNumber); + } + + private static bool ShouldIncrementPreReleaseNumber(IncrementMode mode, bool hasPreReleaseTag, bool integrityCondition) + => hasPreReleaseTag && (mode == IncrementMode.Standard || (mode == IncrementMode.EnsureIntegrity && integrityCondition)); + private static (SemanticVersion Version, bool Found) SelectAlternativeIfGreater( + SemanticVersion semanticVersion, SemanticVersion?[] alternativeSemanticVersions) + { var foundAlternativeSemanticVersion = false; foreach (var alternativeSemanticVersion in alternativeSemanticVersions) { @@ -444,15 +424,12 @@ public SemanticVersion Increment( foundAlternativeSemanticVersion = true; } - major = semanticVersion.Major; - minor = semanticVersion.Minor; - patch = semanticVersion.Patch; - - if (foundAlternativeSemanticVersion && increment == VersionField.None) - { - preReleaseNumber = 1; - } + return (semanticVersion, foundAlternativeSemanticVersion); + } + private SemanticVersion BuildIncrementedVersion( + long major, long minor, long patch, long? preReleaseNumber, bool hasPreReleaseTag, string? label) + { string preReleaseTagName; if (hasPreReleaseTag) { @@ -464,14 +441,12 @@ public SemanticVersion Increment( preReleaseTagName = string.Empty; } - if (label is null || preReleaseTagName == label) + if (label is not null && preReleaseTagName != label) { - return new SemanticVersion(this) { Major = major, Minor = minor, Patch = patch, PreReleaseTag = new SemanticVersionPreReleaseTag(preReleaseTagName, preReleaseNumber, true) }; + preReleaseNumber = 1; + preReleaseTagName = label; } - preReleaseNumber = 1; - preReleaseTagName = label; - return new SemanticVersion(this) { Major = major, diff --git a/src/GitVersion.Core/VersionCalculation/Caching/GitVersionCacheKeyFactory.cs b/src/GitVersion.Core/VersionCalculation/Caching/GitVersionCacheKeyFactory.cs index a2739c9799..4a11fff74c 100644 --- a/src/GitVersion.Core/VersionCalculation/Caching/GitVersionCacheKeyFactory.cs +++ b/src/GitVersion.Core/VersionCalculation/Caching/GitVersionCacheKeyFactory.cs @@ -70,64 +70,19 @@ private List CalculateDirectoryContents(string root) var di = this.fileSystem.DirectoryInfo.New(currentDir); result.Add(di.Name); - string[] subDirs; - try - { - subDirs = this.fileSystem.Directory.GetDirectories(currentDir); - } - // An UnauthorizedAccessException exception will be thrown if we do not have - // discovery permission on a folder or file. It may or may not be acceptable - // to ignore the exception and continue enumerating the remaining files and - // folders. It is also possible (but unlikely) that a DirectoryNotFound exception - // will be raised. This will happen if currentDir has been deleted by - // another application or thread after our call to Directory.Exists. The - // choice of which exceptions to catch depends entirely on the specific task - // you are intending to perform and also on how much you know with certainty - // about the systems on which this code will run. - catch (UnauthorizedAccessException e) - { - this.log.Error(e.Message); - continue; - } - catch (DirectoryNotFoundException e) + var subDirs = TryGetDirectories(currentDir); + if (subDirs is null) { - this.log.Error(e.Message); continue; } - string[] files; - try - { - files = this.fileSystem.Directory.GetFiles(currentDir); - } - catch (UnauthorizedAccessException e) - { - this.log.Error(e.Message); - continue; - } - catch (DirectoryNotFoundException e) + var files = TryGetFiles(currentDir); + if (files is null) { - this.log.Error(e.Message); continue; } - foreach (var file in files) - { - try - { - if (!this.fileSystem.File.Exists(file)) - { - continue; - } - - result.Add(FileSystemHelper.Path.GetFileName(file)); - result.Add(this.fileSystem.File.ReadAllText(file)); - } - catch (IOException e) - { - this.log.Error(e.Message); - } - } + AddFileContents(files, result); // Push the subdirectories onto the stack for traversal. // This could also be done before handing the files. @@ -141,6 +96,72 @@ private List CalculateDirectoryContents(string root) return result; } + private string[]? TryGetDirectories(string currentDir) + { + try + { + return this.fileSystem.Directory.GetDirectories(currentDir); + } + // An UnauthorizedAccessException exception will be thrown if we do not have + // discovery permission on a folder or file. It may or may not be acceptable + // to ignore the exception and continue enumerating the remaining files and + // folders. It is also possible (but unlikely) that a DirectoryNotFound exception + // will be raised. This will happen if currentDir has been deleted by + // another application or thread after our call to Directory.Exists. The + // choice of which exceptions to catch depends entirely on the specific task + // you are intending to perform and also on how much you know with certainty + // about the systems on which this code will run. + catch (UnauthorizedAccessException e) + { + this.log.Error(e.Message); + return null; + } + catch (DirectoryNotFoundException e) + { + this.log.Error(e.Message); + return null; + } + } + + private string[]? TryGetFiles(string currentDir) + { + try + { + return this.fileSystem.Directory.GetFiles(currentDir); + } + catch (UnauthorizedAccessException e) + { + this.log.Error(e.Message); + return null; + } + catch (DirectoryNotFoundException e) + { + this.log.Error(e.Message); + return null; + } + } + + private void AddFileContents(string[] files, List result) + { + foreach (var file in files) + { + try + { + if (!this.fileSystem.File.Exists(file)) + { + continue; + } + + result.Add(FileSystemHelper.Path.GetFileName(file)); + result.Add(this.fileSystem.File.ReadAllText(file)); + } + catch (IOException e) + { + this.log.Error(e.Message); + } + } + } + private string GetRepositorySnapshotHash() { var head = this.repositoryStore.Head; diff --git a/src/GitVersion.Core/VersionCalculation/EffectiveBranchConfigurationFinder.cs b/src/GitVersion.Core/VersionCalculation/EffectiveBranchConfigurationFinder.cs index 6ac9ffdbff..4a733696b7 100644 --- a/src/GitVersion.Core/VersionCalculation/EffectiveBranchConfigurationFinder.cs +++ b/src/GitVersion.Core/VersionCalculation/EffectiveBranchConfigurationFinder.cs @@ -32,41 +32,37 @@ private IEnumerable GetEffectiveConfigurationsRecu branchConfiguration = childBranchConfiguration.Inherit(branchConfiguration); } - IBranch[] sourceBranches = []; - if (branchConfiguration.Increment == IncrementStrategy.Inherit) + if (branchConfiguration.Increment != IncrementStrategy.Inherit) { - // At this point we need to check if source branches are available. - sourceBranches = [.. this.repositoryStore.GetSourceBranches(branch, configuration, traversedBranches)]; + yield return new(new(configuration, branchConfiguration), branch); + yield break; + } - if (sourceBranches.Length == 0) + // At this point we need to check if source branches are available. + IBranch[] sourceBranches = [.. this.repositoryStore.GetSourceBranches(branch, configuration, traversedBranches)]; + + if (sourceBranches.Length == 0) + { + // Because the actual branch is marked with the inherit increment strategy we need to either skip the iteration or go further + // while inheriting from the fallback branch configuration. This behavior is configurable via the increment settings of the configuration. + var skipTraversingOfOrphanedBranches = configuration.Increment == IncrementStrategy.Inherit; + this.log.Info( + $"An orphaned branch '{branch}' has been detected and will be skipped={skipTraversingOfOrphanedBranches}." + ); + if (!skipTraversingOfOrphanedBranches) { - // Because the actual branch is marked with the inherit increment strategy we need to either skip the iteration or go further - // while inheriting from the fallback branch configuration. This behavior is configurable via the increment settings of the configuration. - var skipTraversingOfOrphanedBranches = configuration.Increment == IncrementStrategy.Inherit; - this.log.Info( - $"An orphaned branch '{branch}' has been detected and will be skipped={skipTraversingOfOrphanedBranches}." - ); - if (skipTraversingOfOrphanedBranches) - { - yield break; - } + yield return new(new(configuration, branchConfiguration), branch); } + yield break; } - if (branchConfiguration.Increment == IncrementStrategy.Inherit && sourceBranches.Length != 0) + foreach (var sourceBranch in sourceBranches) { - foreach (var sourceBranch in sourceBranches) + foreach (var effectiveConfiguration + in GetEffectiveConfigurationsRecursive(sourceBranch, configuration, branchConfiguration, traversedBranches)) { - foreach (var effectiveConfiguration - in GetEffectiveConfigurationsRecursive(sourceBranch, configuration, branchConfiguration, traversedBranches)) - { - yield return effectiveConfiguration; - } + yield return effectiveConfiguration; } } - else - { - yield return new(new(configuration, branchConfiguration), branch); - } } } diff --git a/src/GitVersion.Core/VersionCalculation/Mainline/NonTrunk/MergeCommitOnNonTrunkBase.cs b/src/GitVersion.Core/VersionCalculation/Mainline/NonTrunk/MergeCommitOnNonTrunkBase.cs index 3b07c5b9e5..07c0f66e31 100644 --- a/src/GitVersion.Core/VersionCalculation/Mainline/NonTrunk/MergeCommitOnNonTrunkBase.cs +++ b/src/GitVersion.Core/VersionCalculation/Mainline/NonTrunk/MergeCommitOnNonTrunkBase.cs @@ -30,44 +30,53 @@ IEnumerable GetIncrementsInternal() ); context.Label ??= baseVersion.Operator?.Label; + context.Increment = ConsolidateIncrement(commit, context, baseVersion); + ApplyBaseVersion(context, baseVersion); - var effectiveConfiguration = commit.GetEffectiveConfiguration(context.Configuration); - var increment = VersionField.None; - if (!effectiveConfiguration.PreventIncrementOfMergedBranch) - { - increment = increment.Consolidate(context.Increment); - } + yield break; + } + } - if (!effectiveConfiguration.PreventIncrementWhenBranchMerged) - { - increment = increment.Consolidate(baseVersion.Operator?.Increment); - } + private static VersionField ConsolidateIncrement(MainlineCommit commit, MainlineContext context, BaseVersion baseVersion) + { + var effectiveConfiguration = commit.GetEffectiveConfiguration(context.Configuration); + var increment = VersionField.None; - if (effectiveConfiguration.CommitMessageIncrementing != CommitMessageIncrementMode.Disabled) - { - increment = increment.Consolidate(commit.Increment); - } - context.Increment = increment; + if (!effectiveConfiguration.PreventIncrementOfMergedBranch) + { + increment = increment.Consolidate(context.Increment); + } - if (baseVersion.BaseVersionSource is not null) - { - context.BaseVersionSource = baseVersion.BaseVersionSource; - context.SemanticVersion = baseVersion.SemanticVersion; - } - else - { - if (baseVersion.SemanticVersion != SemanticVersion.Empty) - { - context.AlternativeSemanticVersions.Add(baseVersion.SemanticVersion); - } + if (!effectiveConfiguration.PreventIncrementWhenBranchMerged) + { + increment = increment.Consolidate(baseVersion.Operator?.Increment); + } - if (baseVersion.Operator?.AlternativeSemanticVersion is not null) - { - context.AlternativeSemanticVersions.Add(baseVersion.Operator.AlternativeSemanticVersion); - } - } + if (effectiveConfiguration.CommitMessageIncrementing != CommitMessageIncrementMode.Disabled) + { + increment = increment.Consolidate(commit.Increment); + } - yield break; + return increment; + } + + private static void ApplyBaseVersion(MainlineContext context, BaseVersion baseVersion) + { + if (baseVersion.BaseVersionSource is not null) + { + context.BaseVersionSource = baseVersion.BaseVersionSource; + context.SemanticVersion = baseVersion.SemanticVersion; + return; + } + + if (baseVersion.SemanticVersion != SemanticVersion.Empty) + { + context.AlternativeSemanticVersions.Add(baseVersion.SemanticVersion); + } + + if (baseVersion.Operator?.AlternativeSemanticVersion is not null) + { + context.AlternativeSemanticVersions.Add(baseVersion.Operator.AlternativeSemanticVersion); } } } diff --git a/src/GitVersion.Core/VersionCalculation/VersionCalculators/NextVersionCalculator.cs b/src/GitVersion.Core/VersionCalculation/VersionCalculators/NextVersionCalculator.cs index 8397ff3cce..fa3b544de5 100644 --- a/src/GitVersion.Core/VersionCalculation/VersionCalculators/NextVersionCalculator.cs +++ b/src/GitVersion.Core/VersionCalculation/VersionCalculators/NextVersionCalculator.cs @@ -254,49 +254,69 @@ IEnumerable GetNextVersionsInternal() var effectiveBranchConfigurations = this.effectiveBranchConfigurationFinder.GetConfigurations(branch, configuration).ToArray(); foreach (var effectiveBranchConfiguration in effectiveBranchConfigurations) { - using (this.log.IndentLog($"Calculating base versions for '{effectiveBranchConfiguration.Branch.Name}'")) + foreach (var nextVersion in GetNextVersions(effectiveBranchConfiguration, configuration)) { - var strategies = this.versionStrategies.ToList(); - var fallbackVersionStrategy = strategies.Find(element => element is FallbackVersionStrategy); - if (fallbackVersionStrategy is not null) - { - strategies.Remove(fallbackVersionStrategy); - strategies.Add(fallbackVersionStrategy); - } - - var atLeastOneBaseVersionReturned = false; - foreach (var versionStrategy in strategies) - { - if (atLeastOneBaseVersionReturned && versionStrategy is FallbackVersionStrategy) - { - continue; - } - - using (this.log.IndentLog($"[Using '{versionStrategy.GetType().Name}' strategy]")) - { - foreach (var baseVersion in versionStrategy.GetBaseVersions(effectiveBranchConfiguration)) - { - this.log.Info(baseVersion.ToString()); - if (!IncludeVersion(baseVersion, configuration.Ignore)) - { - continue; - } - - atLeastOneBaseVersionReturned = true; - - yield return new NextVersion( - incrementedVersion: baseVersion.GetIncrementedVersion(), - baseVersion: baseVersion, - configuration: effectiveBranchConfiguration - ); - } - } - } + yield return nextVersion; } } } } + private IEnumerable GetNextVersions(EffectiveBranchConfiguration effectiveBranchConfiguration, IGitVersionConfiguration configuration) + { + using (this.log.IndentLog($"Calculating base versions for '{effectiveBranchConfiguration.Branch.Name}'")) + { + var atLeastOneBaseVersionReturned = false; + foreach (var versionStrategy in OrderStrategiesWithFallbackLast()) + { + if (atLeastOneBaseVersionReturned && versionStrategy is FallbackVersionStrategy) + { + continue; + } + + foreach (var nextVersion in GetNextVersions(versionStrategy, effectiveBranchConfiguration, configuration)) + { + atLeastOneBaseVersionReturned = true; + yield return nextVersion; + } + } + } + } + + private IEnumerable GetNextVersions(IVersionStrategy versionStrategy, EffectiveBranchConfiguration effectiveBranchConfiguration, IGitVersionConfiguration configuration) + { + using (this.log.IndentLog($"[Using '{versionStrategy.GetType().Name}' strategy]")) + { + foreach (var baseVersion in versionStrategy.GetBaseVersions(effectiveBranchConfiguration)) + { + this.log.Info(baseVersion.ToString()); + if (!IncludeVersion(baseVersion, configuration.Ignore)) + { + continue; + } + + yield return new NextVersion( + incrementedVersion: baseVersion.GetIncrementedVersion(), + baseVersion: baseVersion, + configuration: effectiveBranchConfiguration + ); + } + } + } + + private List OrderStrategiesWithFallbackLast() + { + var strategies = this.versionStrategies.ToList(); + var fallbackVersionStrategy = strategies.Find(element => element is FallbackVersionStrategy); + if (fallbackVersionStrategy is not null) + { + strategies.Remove(fallbackVersionStrategy); + strategies.Add(fallbackVersionStrategy); + } + + return strategies; + } + private bool IncludeVersion(IBaseVersion baseVersion, IIgnoreConfiguration ignoreConfiguration) { foreach (var versionFilter in ignoreConfiguration.ToFilters()) diff --git a/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/MainlineVersionStrategy.cs b/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/MainlineVersionStrategy.cs index d8439de275..ce1a3d6c0f 100644 --- a/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/MainlineVersionStrategy.cs +++ b/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/MainlineVersionStrategy.cs @@ -140,15 +140,14 @@ private bool IterateOverCommitsRecursive( { traversedCommits ??= []; - var returnTrueWhenTheIncrementIsKnown = false; - - var configuration = iteration.Configuration; - var branchName = iteration.BranchName; - var branch = this.repositoryStore.FindBranch(branchName); - + var branch = this.repositoryStore.FindBranch(iteration.BranchName); var currentBranch = branch; - Lazy>> commitsWasBranchedFromLazy = new( - () => currentBranch is null ? [] : GetCommitsWasBranchedFrom(currentBranch) + TraversalState state = new( + configuration: iteration.Configuration, + branchName: iteration.BranchName, + branch: branch, + taggedSemanticVersions: taggedSemanticVersions, + commitsWasBranchedFromLazy: new(() => currentBranch is null ? [] : GetCommitsWasBranchedFrom(currentBranch)) ); foreach (var item in commitsInReverseOrder) @@ -158,147 +157,190 @@ private bool IterateOverCommitsRecursive( continue; } - if (commitsWasBranchedFromLazy.Value.TryGetValue(item, out var effectiveConfigurationsWasBranchedFrom)) + ApplyBranchedFromTransition(item, iteration, targetBranch, state); + + var (commit, stop) = ProcessCommit(item, iteration, targetLabel, state); + if (stop) { - var effectiveConfigurationWasBranchedFrom = effectiveConfigurationsWasBranchedFrom[0]; + return true; + } - if (configuration.IsMainBranch != true || effectiveConfigurationWasBranchedFrom.Value.IsMainBranch == true) - { - var excludeBranch = branch; - if (effectiveConfigurationsWasBranchedFrom.Any(element => - !element.Branch.Equals(effectiveConfigurationWasBranchedFrom.Branch) - && element.Branch.Equals(targetBranch))) - { - iteration.CreateCommit(null, targetBranch.Name, Context.Configuration.GetBranchConfiguration(targetBranch)); - } - configuration = effectiveConfigurationWasBranchedFrom.Value; - branchName = effectiveConfigurationWasBranchedFrom.Branch.Name; - - branch = this.repositoryStore.FindBranch(branchName); - - var branchPointer = branch; - IBranch[] excludeBranches = excludeBranch is null ? [] : [excludeBranch]; - commitsWasBranchedFromLazy = new Lazy>> - (() => branchPointer is null ? [] - : GetCommitsWasBranchedFrom(branchPointer, excludeBranches) - ); - - var taggedSemanticVersion = TaggedSemanticVersions.OfBranch; - if ((configuration.TrackMergeTarget ?? Context.Configuration.TrackMergeTarget) == true) - { - taggedSemanticVersion |= TaggedSemanticVersions.OfMergeTargets; - } - if ((configuration.TracksReleaseBranches ?? Context.Configuration.TracksReleaseBranches) == true) - { - taggedSemanticVersion |= TaggedSemanticVersions.OfReleaseBranches; - } - if (!(configuration.IsMainBranch == true || configuration.IsReleaseBranch == true)) - { - taggedSemanticVersion |= TaggedSemanticVersions.OfMainBranches; - } - taggedSemanticVersions = this.taggedSemanticVersionService.GetTaggedSemanticVersions( - branch: effectiveConfigurationWasBranchedFrom.Branch, - configuration: Context.Configuration, - label: null, - notOlderThan: Context.CurrentCommit.When, - taggedSemanticVersion: taggedSemanticVersion - ); - } + if (item.IsMergeCommit + && HandleMergeCommit(item, commit, iteration, targetBranch, targetLabel, state, traversedCommits)) + { + return true; } + } + return false; + } - var commit = iteration.CreateCommit(item, branchName, configuration); + private void ApplyBranchedFromTransition( + ICommit item, MainlineIteration iteration, IBranch targetBranch, TraversalState state) + { + if (!state.CommitsWasBranchedFromLazy.Value.TryGetValue(item, out var effectiveConfigurationsWasBranchedFrom)) + { + return; + } - var semanticVersions = taggedSemanticVersions[item].ToArray(); - commit.AddSemanticVersions(semanticVersions.Select(element => element.Value)); + var effectiveConfigurationWasBranchedFrom = effectiveConfigurationsWasBranchedFrom[0]; - var label = targetLabel ?? new EffectiveConfiguration( - configuration: Context.Configuration, - branchConfiguration: configuration - ).GetBranchSpecificLabel(branchName, null, this.environment); + if (state.Configuration.IsMainBranch == true && effectiveConfigurationWasBranchedFrom.Value.IsMainBranch != true) + { + return; + } - foreach (var semanticVersion in semanticVersions) - { - if (!semanticVersion.Value.IsMatchForBranchSpecificLabel(label)) - { - continue; - } + var excludeBranch = state.Branch; + if (effectiveConfigurationsWasBranchedFrom.Any(element => + !element.Branch.Equals(effectiveConfigurationWasBranchedFrom.Branch) + && element.Branch.Equals(targetBranch))) + { + iteration.CreateCommit(null, targetBranch.Name, Context.Configuration.GetBranchConfiguration(targetBranch)); + } - if (configuration.Increment != IncrementStrategy.Inherit) - { - return true; - } + state.Configuration = effectiveConfigurationWasBranchedFrom.Value; + state.BranchName = effectiveConfigurationWasBranchedFrom.Branch.Name; + state.Branch = this.repositoryStore.FindBranch(state.BranchName); - returnTrueWhenTheIncrementIsKnown = true; - } + var branchPointer = state.Branch; + IBranch[] excludeBranches = excludeBranch is null ? [] : [excludeBranch]; + state.CommitsWasBranchedFromLazy = new( + () => branchPointer is null ? [] : GetCommitsWasBranchedFrom(branchPointer, excludeBranches) + ); - if (returnTrueWhenTheIncrementIsKnown && configuration.Increment != IncrementStrategy.Inherit) - { - return true; - } + var taggedSemanticVersion = TaggedSemanticVersions.OfBranch; + if ((state.Configuration.TrackMergeTarget ?? Context.Configuration.TrackMergeTarget) == true) + { + taggedSemanticVersion |= TaggedSemanticVersions.OfMergeTargets; + } + if ((state.Configuration.TracksReleaseBranches ?? Context.Configuration.TracksReleaseBranches) == true) + { + taggedSemanticVersion |= TaggedSemanticVersions.OfReleaseBranches; + } + if (!(state.Configuration.IsMainBranch == true || state.Configuration.IsReleaseBranch == true)) + { + taggedSemanticVersion |= TaggedSemanticVersions.OfMainBranches; + } + state.TaggedSemanticVersions = this.taggedSemanticVersionService.GetTaggedSemanticVersions( + branch: effectiveConfigurationWasBranchedFrom.Branch, + configuration: Context.Configuration, + label: null, + notOlderThan: Context.CurrentCommit.When, + taggedSemanticVersion: taggedSemanticVersion + ); + } - if (!item.IsMergeCommit) - { - continue; - } + private (MainlineCommit Commit, bool Stop) ProcessCommit( + ICommit item, MainlineIteration iteration, string? targetLabel, TraversalState state) + { + var commit = iteration.CreateCommit(item, state.BranchName, state.Configuration); - Lazy> mergedCommitsInReverseOrderLazy = new( - () => [.. this.incrementStrategyFinder.GetMergedCommits(item, 1, Context.Configuration.Ignore).Reverse()] - ); + var semanticVersions = state.TaggedSemanticVersions[item].ToArray(); + commit.AddSemanticVersions(semanticVersions.Select(element => element.Value)); + + var label = targetLabel ?? new EffectiveConfiguration( + configuration: Context.Configuration, + branchConfiguration: state.Configuration + ).GetBranchSpecificLabel(state.BranchName, null, this.environment); - if ((configuration.TrackMergeMessage ?? Context.Configuration.TrackMergeMessage) != true - || !MergeMessage.TryParse(item, Context.Configuration, out var mergeMessage)) + foreach (var semanticVersion in semanticVersions) + { + if (!semanticVersion.Value.IsMatchForBranchSpecificLabel(label)) { continue; } - if (mergeMessage.MergedBranch is null || mergeMessage.MergedBranch.EquivalentTo(branchName.WithoutOrigin)) + if (state.Configuration.Increment != IncrementStrategy.Inherit) { - continue; + return (commit, true); } - var childConfiguration = Context.Configuration.GetBranchConfiguration(mergeMessage.MergedBranch); - var childBranchName = mergeMessage.MergedBranch; + state.ReturnTrueWhenTheIncrementIsKnown = true; + } - if (childConfiguration.IsMainBranch == true) - { - if (configuration.IsMainBranch == true) - { - throw new NotImplementedException(); - } + if (state.ReturnTrueWhenTheIncrementIsKnown && state.Configuration.Increment != IncrementStrategy.Inherit) + { + return (commit, true); + } - mergedCommitsInReverseOrderLazy = new( - () => [.. this.incrementStrategyFinder.GetMergedCommits(item, 0, Context.Configuration.Ignore).Reverse()] - ); - childConfiguration = configuration; - childBranchName = iteration.BranchName; - } + return (commit, false); + } - var childIteration = CreateIteration( - branchName: childBranchName, - configuration: childConfiguration, - parentIteration: iteration, - parentCommit: commit - ); + private bool HandleMergeCommit( + ICommit item, MainlineCommit commit, MainlineIteration iteration, IBranch targetBranch, + string? targetLabel, TraversalState state, HashSet traversedCommits) + { + Lazy> mergedCommitsInReverseOrderLazy = new( + () => [.. this.incrementStrategyFinder.GetMergedCommits(item, 1, Context.Configuration.Ignore).Reverse()] + ); + + if ((state.Configuration.TrackMergeMessage ?? Context.Configuration.TrackMergeMessage) != true + || !MergeMessage.TryParse(item, Context.Configuration, out var mergeMessage)) + { + return false; + } - var done = IterateOverCommitsRecursive( - commitsInReverseOrder: mergedCommitsInReverseOrderLazy.Value, - iteration: childIteration, - targetBranch: targetBranch, - targetLabel: targetLabel, - taggedSemanticVersions: taggedSemanticVersions, - traversedCommits: traversedCommits); + if (mergeMessage.MergedBranch is null || mergeMessage.MergedBranch.EquivalentTo(state.BranchName.WithoutOrigin)) + { + return false; + } - commit.AddChildIteration(childIteration); - if (done) + var childConfiguration = Context.Configuration.GetBranchConfiguration(mergeMessage.MergedBranch); + var childBranchName = mergeMessage.MergedBranch; + + if (childConfiguration.IsMainBranch == true) + { + if (state.Configuration.IsMainBranch == true) { - return true; + throw new NotImplementedException(); } - traversedCommits.AddRange(mergedCommitsInReverseOrderLazy.Value); + mergedCommitsInReverseOrderLazy = new( + () => [.. this.incrementStrategyFinder.GetMergedCommits(item, 0, Context.Configuration.Ignore).Reverse()] + ); + childConfiguration = state.Configuration; + childBranchName = iteration.BranchName; } + + var childIteration = CreateIteration( + branchName: childBranchName, + configuration: childConfiguration, + parentIteration: iteration, + parentCommit: commit + ); + + var done = IterateOverCommitsRecursive( + commitsInReverseOrder: mergedCommitsInReverseOrderLazy.Value, + iteration: childIteration, + targetBranch: targetBranch, + targetLabel: targetLabel, + taggedSemanticVersions: state.TaggedSemanticVersions, + traversedCommits: traversedCommits); + + commit.AddChildIteration(childIteration); + if (done) + { + return true; + } + + traversedCommits.AddRange(mergedCommitsInReverseOrderLazy.Value); return false; } + private sealed class TraversalState( + IBranchConfiguration configuration, + ReferenceName branchName, + IBranch? branch, + ILookup taggedSemanticVersions, + Lazy>> commitsWasBranchedFromLazy) + { + public IBranchConfiguration Configuration { get; set; } = configuration; + public ReferenceName BranchName { get; set; } = branchName; + public IBranch? Branch { get; set; } = branch; + public ILookup TaggedSemanticVersions { get; set; } = taggedSemanticVersions; + public Lazy>> CommitsWasBranchedFromLazy { get; set; } = commitsWasBranchedFromLazy; + public bool ReturnTrueWhenTheIncrementIsKnown { get; set; } + } + private Dictionary> GetCommitsWasBranchedFrom( IBranch branch, params IBranch[] excludedBranches) { diff --git a/src/GitVersion.MsBuild.Tests/Helpers/EventArgsFormatting.cs b/src/GitVersion.MsBuild.Tests/Helpers/EventArgsFormatting.cs index a0781dee3f..e3aa0c711f 100644 --- a/src/GitVersion.MsBuild.Tests/Helpers/EventArgsFormatting.cs +++ b/src/GitVersion.MsBuild.Tests/Helpers/EventArgsFormatting.cs @@ -155,29 +155,7 @@ int threadId else { format.Append("{1}"); - - if (lineNumber == 0) - { - format.Append(" : "); - } - else - { - if (columnNumber == 0) - { - format.Append(endLineNumber == 0 ? "({2}): " : "({2}-{7}): "); - } - else - { - if (endLineNumber == 0) - { - format.Append(endColumnNumber == 0 ? "({2},{3}): " : "({2},{3}-{8}): "); - } - else - { - format.Append(endColumnNumber == 0 ? "({2}-{7},{3}): " : "({2},{3},{7},{8}): "); - } - } - } + format.Append(GetPositionFormat(lineNumber, endLineNumber, columnNumber, endColumnNumber)); } if (!string.IsNullOrWhiteSpace(subcategory)) @@ -230,6 +208,29 @@ int threadId return formattedMessage.ToString(); } + /// + /// Selects the line/column position format placeholder for the given coordinates. + /// + private static string GetPositionFormat(int lineNumber, int endLineNumber, int columnNumber, int endColumnNumber) + { + if (lineNumber == 0) + { + return " : "; + } + + if (columnNumber == 0) + { + return endLineNumber == 0 ? "({2}): " : "({2}-{7}): "; + } + + if (endLineNumber == 0) + { + return endColumnNumber == 0 ? "({2},{3}): " : "({2},{3}-{8}): "; + } + + return endColumnNumber == 0 ? "({2}-{7},{3}): " : "({2},{3},{7},{8}): "; + } + /// /// Splits strings on 'newLines' with tolerance for Everett and Dogfood builds. /// diff --git a/src/GitVersion.Output/AssemblyInfo/AssemblyInfoFileUpdater.cs b/src/GitVersion.Output/AssemblyInfo/AssemblyInfoFileUpdater.cs index 4ede39fd3e..df64c9e5f2 100644 --- a/src/GitVersion.Output/AssemblyInfo/AssemblyInfoFileUpdater.cs +++ b/src/GitVersion.Output/AssemblyInfo/AssemblyInfoFileUpdater.cs @@ -31,64 +31,68 @@ public void Execute(GitVersionVariables variables, AssemblyInfoContext context) log.Info("Updating assembly info files"); log.Info($"Found {assemblyInfoFiles.Count} files"); - var assemblyVersion = variables.AssemblySemVer; - var assemblyVersionString = !assemblyVersion.IsNullOrWhiteSpace() ? $"AssemblyVersion(\"{assemblyVersion}\")" : null; + foreach (var assemblyInfoFile in assemblyInfoFiles) + { + UpdateAssemblyInfoFile(assemblyInfoFile, variables); + } - var assemblyInfoVersion = variables.InformationalVersion; - var assemblyInfoVersionString = !assemblyInfoVersion.IsNullOrWhiteSpace() ? $"AssemblyInformationalVersion(\"{assemblyInfoVersion}\")" : null; + CommitChanges(); + } - var assemblyFileVersion = variables.AssemblySemFileVer; - var assemblyFileVersionString = !assemblyFileVersion.IsNullOrWhiteSpace() ? $"AssemblyFileVersion(\"{assemblyFileVersion}\")" : null; + private void UpdateAssemblyInfoFile(IFileInfo assemblyInfoFile, GitVersionVariables variables) + { + var localAssemblyInfo = assemblyInfoFile.FullName; + var backupAssemblyInfo = localAssemblyInfo + ".bak"; + fileSystem.File.Copy(localAssemblyInfo, backupAssemblyInfo, true); - foreach (var assemblyInfoFile in assemblyInfoFiles) + this.restoreBackupTasks.Add(() => { - var localAssemblyInfo = assemblyInfoFile.FullName; - var backupAssemblyInfo = localAssemblyInfo + ".bak"; - fileSystem.File.Copy(localAssemblyInfo, backupAssemblyInfo, true); - - this.restoreBackupTasks.Add(() => + if (fileSystem.File.Exists(localAssemblyInfo)) { - if (fileSystem.File.Exists(localAssemblyInfo)) - { - fileSystem.File.Delete(localAssemblyInfo); - } + fileSystem.File.Delete(localAssemblyInfo); + } - fileSystem.File.Move(backupAssemblyInfo, localAssemblyInfo); - }); + fileSystem.File.Move(backupAssemblyInfo, localAssemblyInfo); + }); - this.cleanupBackupTasks.Add(() => fileSystem.File.Delete(backupAssemblyInfo)); + this.cleanupBackupTasks.Add(() => fileSystem.File.Delete(backupAssemblyInfo)); - var originalFileContents = fileSystem.File.ReadAllText(localAssemblyInfo); - var fileContents = originalFileContents; - var appendedAttributes = false; + var originalFileContents = fileSystem.File.ReadAllText(localAssemblyInfo); + var fileContents = originalFileContents; + var appendedAttributes = false; + var extension = assemblyInfoFile.Extension; - if (!assemblyVersion.IsNullOrWhiteSpace()) - { - fileContents = ReplaceOrInsertAfterLastAssemblyAttributeOrAppend(RegexPatterns.Output.AssemblyVersionRegex, fileContents, assemblyVersionString, assemblyInfoFile.Extension, ref appendedAttributes); - } + if (!variables.AssemblySemVer.IsNullOrWhiteSpace()) + { + var result = ReplaceOrInsertAfterLastAssemblyAttributeOrAppend(RegexPatterns.Output.AssemblyVersionRegex, fileContents, $"AssemblyVersion(\"{variables.AssemblySemVer}\")", extension); + fileContents = result.Content; + appendedAttributes |= result.Appended; + } - if (!assemblyFileVersion.IsNullOrWhiteSpace()) - { - fileContents = ReplaceOrInsertAfterLastAssemblyAttributeOrAppend(RegexPatterns.Output.AssemblyFileVersionRegex, fileContents, assemblyFileVersionString, assemblyInfoFile.Extension, ref appendedAttributes); - } + if (!variables.AssemblySemFileVer.IsNullOrWhiteSpace()) + { + var result = ReplaceOrInsertAfterLastAssemblyAttributeOrAppend(RegexPatterns.Output.AssemblyFileVersionRegex, fileContents, $"AssemblyFileVersion(\"{variables.AssemblySemFileVer}\")", extension); + fileContents = result.Content; + appendedAttributes |= result.Appended; + } - if (!assemblyInfoVersion.IsNullOrWhiteSpace()) - { - fileContents = ReplaceOrInsertAfterLastAssemblyAttributeOrAppend(RegexPatterns.Output.AssemblyInfoVersionRegex, fileContents, assemblyInfoVersionString, assemblyInfoFile.Extension, ref appendedAttributes); - } + if (!variables.InformationalVersion.IsNullOrWhiteSpace()) + { + var result = ReplaceOrInsertAfterLastAssemblyAttributeOrAppend(RegexPatterns.Output.AssemblyInfoVersionRegex, fileContents, $"AssemblyInformationalVersion(\"{variables.InformationalVersion}\")", extension); + fileContents = result.Content; + appendedAttributes |= result.Appended; + } - if (appendedAttributes) - { - // If we appended any attributes, put a new line after them - fileContents += NewLine; - } + if (appendedAttributes) + { + // If we appended any attributes, put a new line after them + fileContents += NewLine; + } - if (originalFileContents != fileContents) - { - fileSystem.File.WriteAllText(localAssemblyInfo, fileContents); - } + if (originalFileContents != fileContents) + { + fileSystem.File.WriteAllText(localAssemblyInfo, fileContents); } - CommitChanges(); } public void Dispose() @@ -113,13 +117,13 @@ private void CommitChanges() this.restoreBackupTasks.Clear(); } - private string ReplaceOrInsertAfterLastAssemblyAttributeOrAppend(Regex replaceRegex, string inputString, string? replaceString, string fileExtension, ref bool appendedAttributes) + private (string Content, bool Appended) ReplaceOrInsertAfterLastAssemblyAttributeOrAppend(Regex replaceRegex, string inputString, string? replaceString, string fileExtension) { var assemblyAddFormat = this.templateManager.GetAddFormatFor(fileExtension); if (replaceRegex.IsMatch(inputString) && replaceString != null) { - return replaceRegex.Replace(inputString, replaceString); + return (replaceRegex.Replace(inputString, replaceString), false); } if (this.assemblyAttributeRegexes.TryGetValue(fileExtension, out var assemblyRegex)) @@ -140,7 +144,7 @@ private string ReplaceOrInsertAfterLastAssemblyAttributeOrAppend(Regex replaceRe } replacementString += NewLine; - return inputString.Replace(lastMatch.Value, replacementString); + return (inputString.Replace(lastMatch.Value, replacementString), false); } } @@ -149,8 +153,7 @@ private string ReplaceOrInsertAfterLastAssemblyAttributeOrAppend(Regex replaceRe inputString += NewLine + string.Format(assemblyAddFormat, replaceString); } - appendedAttributes = true; - return inputString; + return (inputString, true); } private IEnumerable GetAssemblyInfoFiles(AssemblyInfoContext context) diff --git a/src/GitVersion.Output/AssemblyInfo/ProjectFileUpdater.cs b/src/GitVersion.Output/AssemblyInfo/ProjectFileUpdater.cs index 5ffabe4554..72b8d28395 100644 --- a/src/GitVersion.Output/AssemblyInfo/ProjectFileUpdater.cs +++ b/src/GitVersion.Output/AssemblyInfo/ProjectFileUpdater.cs @@ -30,75 +30,80 @@ public void Execute(GitVersionVariables variables, AssemblyInfoContext context) var projectFilesToUpdate = GetProjectFiles(context).ToList(); + foreach (var localProjectFile in projectFilesToUpdate.Select(projectFile => projectFile.FullName)) + { + UpdateProjectFile(localProjectFile, variables); + } + + CommitChanges(); + } + + private void UpdateProjectFile(string localProjectFile, GitVersionVariables variables) + { var assemblyVersion = variables.AssemblySemVer; var assemblyInfoVersion = variables.InformationalVersion; var assemblyFileVersion = variables.AssemblySemFileVer; var packageVersion = variables.SemVer; - foreach (var localProjectFile in projectFilesToUpdate.Select(projectFile => projectFile.FullName)) + var originalFileContents = fileSystem.File.ReadAllText(localProjectFile); + XElement fileXml; + try { - var originalFileContents = fileSystem.File.ReadAllText(localProjectFile); - XElement fileXml; - try - { - fileXml = XElement.Parse(originalFileContents); - } - catch (XmlException e) - { - throw new XmlException($"Unable to parse file as xml: {localProjectFile}", e); - } + fileXml = XElement.Parse(originalFileContents); + } + catch (XmlException e) + { + throw new XmlException($"Unable to parse file as xml: {localProjectFile}", e); + } - if (!CanUpdateProjectFile(fileXml)) - { - log.Warning($"Unable to update file: {localProjectFile}"); - continue; - } + if (!CanUpdateProjectFile(fileXml)) + { + log.Warning($"Unable to update file: {localProjectFile}"); + return; + } - log.Debug($"Update file: {localProjectFile}"); + log.Debug($"Update file: {localProjectFile}"); - var backupProjectFile = localProjectFile + ".bak"; - fileSystem.File.Copy(localProjectFile, backupProjectFile, true); + var backupProjectFile = localProjectFile + ".bak"; + fileSystem.File.Copy(localProjectFile, backupProjectFile, true); - this.restoreBackupTasks.Add(() => + this.restoreBackupTasks.Add(() => + { + if (fileSystem.File.Exists(localProjectFile)) { - if (fileSystem.File.Exists(localProjectFile)) - { - fileSystem.File.Delete(localProjectFile); - } - - fileSystem.File.Move(backupProjectFile, localProjectFile); - }); + fileSystem.File.Delete(localProjectFile); + } - this.cleanupBackupTasks.Add(() => fileSystem.File.Delete(backupProjectFile)); + fileSystem.File.Move(backupProjectFile, localProjectFile); + }); - if (!assemblyVersion.IsNullOrWhiteSpace()) - { - UpdateProjectVersionElement(fileXml, AssemblyVersionElement, assemblyVersion); - } + this.cleanupBackupTasks.Add(() => fileSystem.File.Delete(backupProjectFile)); - if (!assemblyFileVersion.IsNullOrWhiteSpace()) - { - UpdateProjectVersionElement(fileXml, FileVersionElement, assemblyFileVersion); - } + if (!assemblyVersion.IsNullOrWhiteSpace()) + { + UpdateProjectVersionElement(fileXml, AssemblyVersionElement, assemblyVersion); + } - if (!assemblyInfoVersion.IsNullOrWhiteSpace()) - { - UpdateProjectVersionElement(fileXml, InformationalVersionElement, assemblyInfoVersion); - } + if (!assemblyFileVersion.IsNullOrWhiteSpace()) + { + UpdateProjectVersionElement(fileXml, FileVersionElement, assemblyFileVersion); + } - if (!packageVersion.IsNullOrWhiteSpace()) - { - UpdateProjectVersionElement(fileXml, VersionElement, packageVersion); - } + if (!assemblyInfoVersion.IsNullOrWhiteSpace()) + { + UpdateProjectVersionElement(fileXml, InformationalVersionElement, assemblyInfoVersion); + } - var outputXmlString = fileXml.ToString(); - if (originalFileContents != outputXmlString) - { - fileSystem.File.WriteAllText(localProjectFile, outputXmlString); - } + if (!packageVersion.IsNullOrWhiteSpace()) + { + UpdateProjectVersionElement(fileXml, VersionElement, packageVersion); } - CommitChanges(); + var outputXmlString = fileXml.ToString(); + if (originalFileContents != outputXmlString) + { + fileSystem.File.WriteAllText(localProjectFile, outputXmlString); + } } public bool CanUpdateProjectFile(XElement xmlRoot) diff --git a/src/GitVersion.Output/OutputGenerator/OutputGenerator.cs b/src/GitVersion.Output/OutputGenerator/OutputGenerator.cs index d75b7ee86d..3dc8a9c82c 100644 --- a/src/GitVersion.Output/OutputGenerator/OutputGenerator.cs +++ b/src/GitVersion.Output/OutputGenerator/OutputGenerator.cs @@ -36,44 +36,57 @@ public void Execute(GitVersionVariables variables, OutputContext context) if (gitVersionOptions.Output.Contains(OutputType.DotEnv)) { - List dotEnvEntries = []; - foreach (var (key, value) in variables.OrderBy(x => x.Key)) - { - var prefixedKey = "GitVersion_" + key; - var environmentValue = ""; - if (!value.IsNullOrEmpty()) - { - environmentValue = value; - } - dotEnvEntries.Add($"{prefixedKey}='{environmentValue}'"); - } - - foreach (var dotEnvEntry in dotEnvEntries) - { - this.console.WriteLine(dotEnvEntry); - } - + WriteDotEnv(variables); return; } var json = this.serializer.ToJson(variables); + if (gitVersionOptions.Output.Contains(OutputType.File)) { - var retryOperation = new RetryAction(); - retryOperation.Execute(() => + WriteJsonToFile(json, context); + } + + if (gitVersionOptions.Output.Contains(OutputType.Json)) + { + WriteJsonToConsole(json, variables, gitVersionOptions); + } + } + + private void WriteDotEnv(GitVersionVariables variables) + { + List dotEnvEntries = []; + foreach (var (key, value) in variables.OrderBy(x => x.Key)) + { + var prefixedKey = "GitVersion_" + key; + var environmentValue = ""; + if (!value.IsNullOrEmpty()) { - if (context.OutputFile != null) - { - this.fileSystem.File.WriteAllText(context.OutputFile, json); - } - }); + environmentValue = value; + } + dotEnvEntries.Add($"{prefixedKey}='{environmentValue}'"); } - if (!gitVersionOptions.Output.Contains(OutputType.Json)) + foreach (var dotEnvEntry in dotEnvEntries) { - return; + this.console.WriteLine(dotEnvEntry); } + } + + private void WriteJsonToFile(string json, OutputContext context) + { + var retryOperation = new RetryAction(); + retryOperation.Execute(() => + { + if (context.OutputFile != null) + { + this.fileSystem.File.WriteAllText(context.OutputFile, json); + } + }); + } + private void WriteJsonToConsole(string json, GitVersionVariables variables, GitVersionOptions gitVersionOptions) + { if (gitVersionOptions.ShowVariable is null && gitVersionOptions.Format is null) { this.console.WriteLine(json); @@ -98,26 +111,8 @@ public void Execute(GitVersionVariables variables, OutputContext context) if (gitVersionOptions.Format is not null) { - var format = gitVersionOptions.Format; - var formatted = format.FormatWith(variables, environment); + var formatted = gitVersionOptions.Format.FormatWith(variables, environment); this.console.WriteLine(formatted); - return; - } - - switch (gitVersionOptions.ShowVariable) - { - case null: - this.console.WriteLine(variables.ToString()); - break; - - default: - if (!variables.TryGetValue(gitVersionOptions.ShowVariable, out var part)) - { - throw new WarningException($"'{gitVersionOptions.ShowVariable}' variable does not exist"); - } - - this.console.WriteLine(part); - break; } }