From 2b33d6ff347002e1d7c6a7a77ce328897e209989 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Tue, 6 Apr 2021 13:55:42 -0600 Subject: [PATCH 01/16] Set version to '3.5-alpha' --- version.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.json b/version.json index f851fdf9..f0167361 100644 --- a/version.json +++ b/version.json @@ -1,6 +1,6 @@ { "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "3.4-rc", + "version": "3.5-alpha", "assemblyVersion": { "precision": "revision" }, @@ -9,4 +9,4 @@ "^refs/heads/develop$", "^refs/heads/v\\d+\\.\\d+$" ] -} +} \ No newline at end of file From 6faef508d3156e370688931d734b35c0c55fcba4 Mon Sep 17 00:00:00 2001 From: Matthias Koch Date: Fri, 30 Apr 2021 16:57:39 +0200 Subject: [PATCH 02/16] Update TeamCity documentation --- src/NerdBank.GitVersioning/CloudBuildServices/TeamCity.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/NerdBank.GitVersioning/CloudBuildServices/TeamCity.cs b/src/NerdBank.GitVersioning/CloudBuildServices/TeamCity.cs index e4df2b69..da5367e9 100644 --- a/src/NerdBank.GitVersioning/CloudBuildServices/TeamCity.cs +++ b/src/NerdBank.GitVersioning/CloudBuildServices/TeamCity.cs @@ -8,8 +8,8 @@ /// TeamCity CI build support. /// /// - /// The TeamCIty-specific properties referenced here are documented here: - /// https://confluence.jetbrains.com/display/TCD8/Predefined+Build+Parameters + /// The TeamCity-specific properties referenced here are documented here: + /// https://www.jetbrains.com/help/teamcity/predefined-build-parameters.html /// internal class TeamCity : ICloudBuild { From 50c71756772ac72b77ae4534e53d3a17bb732dc5 Mon Sep 17 00:00:00 2001 From: Matthias Koch Date: Fri, 30 Apr 2021 17:03:21 +0200 Subject: [PATCH 03/16] Add SpaceAutomation support --- src/NerdBank.GitVersioning/CloudBuild.cs | 1 + .../CloudBuildServices/SpaceAutomation.cs | 38 +++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 src/NerdBank.GitVersioning/CloudBuildServices/SpaceAutomation.cs diff --git a/src/NerdBank.GitVersioning/CloudBuild.cs b/src/NerdBank.GitVersioning/CloudBuild.cs index c1025aac..e5417145 100644 --- a/src/NerdBank.GitVersioning/CloudBuild.cs +++ b/src/NerdBank.GitVersioning/CloudBuild.cs @@ -21,6 +21,7 @@ public static class CloudBuild new Jenkins(), new GitLab(), new Travis(), + new SpaceAutomation(), }; /// diff --git a/src/NerdBank.GitVersioning/CloudBuildServices/SpaceAutomation.cs b/src/NerdBank.GitVersioning/CloudBuildServices/SpaceAutomation.cs new file mode 100644 index 00000000..cf1930ab --- /dev/null +++ b/src/NerdBank.GitVersioning/CloudBuildServices/SpaceAutomation.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.IO; + +namespace Nerdbank.GitVersioning.CloudBuildServices +{ + /// + /// SpaceAutomation CI build support. + /// + /// + /// The SpaceAutomation-specific properties referenced here are documented here: + /// https://www.jetbrains.com/help/space/automation-environment-variables.html + /// + internal class SpaceAutomation : ICloudBuild + { + public string BuildingBranch => CloudBuild.IfStartsWith(BuildingRef, "refs/heads/"); + + public string BuildingTag => CloudBuild.IfStartsWith(BuildingRef, "refs/tags/"); + + public string GitCommitId => Environment.GetEnvironmentVariable("JB_SPACE_GIT_REVISION"); + + public bool IsApplicable => this.GitCommitId != null; + + public bool IsPullRequest => false; + + private static string BuildingRef => Environment.GetEnvironmentVariable("JB_SPACE_GIT_BRANCH"); + + public IReadOnlyDictionary SetCloudBuildNumber(string buildNumber, TextWriter stdout, TextWriter stderr) + { + return new Dictionary(); + } + + public IReadOnlyDictionary SetCloudBuildVariable(string name, string value, TextWriter stdout, TextWriter stderr) + { + return new Dictionary(); + } + } +} \ No newline at end of file From f76724d450717da3aaff3204b964d71a37e2980b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Gr=C3=BCnwald?= Date: Sat, 1 May 2021 18:58:45 +0200 Subject: [PATCH 04/16] Abort prepare-release command when version on current branch is not incremented Ensure version on current branch is updated by prepare-release command When the next version for the current branch is set by the user using the '--nextVersion' command line parameter, the next version might be equal to the current version. In that case no commit is created (no changes on the branch), which in turn causes the current branch to be fast-forwarded to the commit on the newly-created release branch when the branches are merged. To prevent this error, abort command if both versions match (there is already a check in place that prevents the version from being decremented). The check only applies to the current branch because the version on the release branch not being incremented is a valid use case. --- .../ReleaseManagerTests.cs | 20 ++++++++++++++++++- src/NerdBank.GitVersioning/ReleaseManager.cs | 13 ++++++++++++ src/nbgv/Program.cs | 1 + 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/NerdBank.GitVersioning.Tests/ReleaseManagerTests.cs b/src/NerdBank.GitVersioning.Tests/ReleaseManagerTests.cs index c69f5120..9ad8c96c 100644 --- a/src/NerdBank.GitVersioning.Tests/ReleaseManagerTests.cs +++ b/src/NerdBank.GitVersioning.Tests/ReleaseManagerTests.cs @@ -392,12 +392,30 @@ public void PrepareRelease_MasterWithVersionDecrement(string initialVersion, str this.WriteVersionFile(versionOptions); // running PrepareRelease should result in an error - // because we're trying to add a prerelease tag to a version without prerelease tag + // because we're setting the version on master to a lower version this.AssertError( () => new ReleaseManager().PrepareRelease(this.RepoPath, releaseUnstableTag, (nextVersion == null ? null : Version.Parse(nextVersion))), ReleasePreparationError.VersionDecrement); } + [Theory] + [InlineData("1.2", "1.2")] + public void PrepareRelease_MasterWithoutVersionIncrement(string initialVersion, string nextVersion) + { + // create and configure repository + this.InitializeSourceControl(); + + // create version.json + var versionOptions = new VersionOptions() { Version = SemanticVersion.Parse(initialVersion) }; + this.WriteVersionFile(versionOptions); + + // running PrepareRelease should result in an error + // because we're trying to set master to the version it already has + this.AssertError( + () => new ReleaseManager().PrepareRelease(this.RepoPath, null, (nextVersion == null ? null : Version.Parse(nextVersion))), + ReleasePreparationError.NoVersionIncrement); + } + [Fact] public void PrepareRelease_DetachedHead() { diff --git a/src/NerdBank.GitVersioning/ReleaseManager.cs b/src/NerdBank.GitVersioning/ReleaseManager.cs index e30efa6a..8ac24c9d 100644 --- a/src/NerdBank.GitVersioning/ReleaseManager.cs +++ b/src/NerdBank.GitVersioning/ReleaseManager.cs @@ -47,6 +47,11 @@ public enum ReleasePreparationError /// VersionDecrement, + /// + /// Branch cannot be set to the specified version because the new version is not higher than the current version + /// + NoVersionIncrement, + /// /// Cannot create a branch because it already exists /// @@ -273,6 +278,14 @@ public void PrepareRelease(string projectDirectory, string releaseUnstableTag = var nextDevVersion = this.GetNextDevVersion(versionOptions, nextVersion, versionIncrement); + // check if the current version on the main branch is different from the next version + // otherwise, both the release branch and the dev branch would have the same version + if (versionOptions.Version.Version == nextDevVersion.Version) + { + this.stderr.WriteLine($"Version on '{originalBranchName}' is already set to next version {nextDevVersion.Version}."); + throw new ReleasePreparationException(ReleasePreparationError.NoVersionIncrement); + } + // check if the release branch already exists if (repository.Branches[releaseBranchName] != null) { diff --git a/src/nbgv/Program.cs b/src/nbgv/Program.cs index 7df6b7bf..e23b2d42 100644 --- a/src/nbgv/Program.cs +++ b/src/nbgv/Program.cs @@ -736,6 +736,7 @@ private static int OnPrepareReleaseCommand(string project, string nextVersion, s case ReleaseManager.ReleasePreparationError.NoVersionFile: return (int)ExitCodes.NoVersionJsonFound; case ReleaseManager.ReleasePreparationError.VersionDecrement: + case ReleaseManager.ReleasePreparationError.NoVersionIncrement: return (int)ExitCodes.InvalidVersionSpec; case ReleaseManager.ReleasePreparationError.BranchAlreadyExists: return (int)ExitCodes.BranchAlreadyExists; From 48ef902eb6be3cd5e09a77e2a317619338ef9f64 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Sat, 1 May 2021 17:47:49 -0600 Subject: [PATCH 05/16] Remove assumption of current branch name in code comment --- src/NerdBank.GitVersioning/ReleaseManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NerdBank.GitVersioning/ReleaseManager.cs b/src/NerdBank.GitVersioning/ReleaseManager.cs index 8ac24c9d..42324946 100644 --- a/src/NerdBank.GitVersioning/ReleaseManager.cs +++ b/src/NerdBank.GitVersioning/ReleaseManager.cs @@ -278,7 +278,7 @@ public void PrepareRelease(string projectDirectory, string releaseUnstableTag = var nextDevVersion = this.GetNextDevVersion(versionOptions, nextVersion, versionIncrement); - // check if the current version on the main branch is different from the next version + // check if the current version on the current branch is different from the next version // otherwise, both the release branch and the dev branch would have the same version if (versionOptions.Version.Version == nextDevVersion.Version) { From dae20a6d15f04d8161fd092c36fdf1f57c021ba1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 May 2021 12:00:32 -0600 Subject: [PATCH 06/16] Bump hosted-git-info in /src/nerdbank-gitversioning.npm (#601) Bumps [hosted-git-info](https://github.com/npm/hosted-git-info) from 2.8.8 to 2.8.9. - [Release notes](https://github.com/npm/hosted-git-info/releases) - [Changelog](https://github.com/npm/hosted-git-info/blob/v2.8.9/CHANGELOG.md) - [Commits](https://github.com/npm/hosted-git-info/compare/v2.8.8...v2.8.9) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/nerdbank-gitversioning.npm/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/nerdbank-gitversioning.npm/yarn.lock b/src/nerdbank-gitversioning.npm/yarn.lock index 58378eda..5d2beb75 100644 --- a/src/nerdbank-gitversioning.npm/yarn.lock +++ b/src/nerdbank-gitversioning.npm/yarn.lock @@ -1222,9 +1222,9 @@ homedir-polyfill@^1.0.1: parse-passwd "^1.0.0" hosted-git-info@^2.1.4: - version "2.8.8" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" - integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg== + version "2.8.9" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" + integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== ignore@^5.1.1: version "5.1.4" From 192d62eee1a6143e49f6e76a81a1082277f93c25 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Tue, 25 May 2021 21:05:19 -0600 Subject: [PATCH 07/16] Improve msbuild documentation --- doc/msbuild.md | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/doc/msbuild.md b/doc/msbuild.md index 5ae13032..10b23e8a 100644 --- a/doc/msbuild.md +++ b/doc/msbuild.md @@ -2,6 +2,23 @@ Installing the `Nerdbank.GitVersioning` package from NuGet into your MSBuild-based projects is the recommended way to add version information to your MSBuild project outputs including assemblies, native dll's, and packages. +If you want the package to affect all the projects in your repo, and you use `PackageReference` (rather than `packages.config`), +you can add this to a repo-level `Directory.Build.props` file: + +```xml + + + +``` + +The condition prevents the `PackageReference` from impacting any `packages.config`-based projects +such as vcxproj that may be in your repo. +Such projects will require individual installation of the Nerdbank.GitVersioning nuget package +using the NuGet Package Manager in Visual Studio. + ## Public releases By default, each build of a Nuget package will include the git commit ID. @@ -21,6 +38,64 @@ You should only build with this property set from one release branch per major.minor version to avoid the risk of producing multiple unique NuGet packages with a colliding version spec. +## Custom build authoring + +If you are writing your own MSBuild targets or properties and need to consume version information, +Nerdbank.GitVersioning is there to help. +The version information created by this package is expressed as MSBuild properties. +These properties are set by the `GetBuildVersion` target defined in this package. +This means any dependency you have on these properties must ensure this target has already executed. +This can be done by defining your own msbuild target like so: + +```xml + + + My assembly version is: $(AssemblyVersion) + + +``` + +In the above example, the `AssemblyVersion` property, which is set by the +`GetBuildVersion` target defined by Nerdbank.GitVersioning, is used to define +another property. +It could also be used to define msbuild items or anything else you want. + +### MSBuild properties defined in `GetBuildVersion` + +Many MSBuild properties are set by `GetBuildVersion` allowing you to define or redefine +properties in virtually any format you like. +The authoritative list is [here](https://github.com/dotnet/Nerdbank.GitVersioning/blob/dae20a6d15f04d8161fd092c36fdf1f57c021ba1/src/Nerdbank.GitVersioning.Tasks/GetBuildVersion.cs#L300-L323) (switch to the default branch to see the current set). + +Below is a snapshot of the properties with example values. +Note that the values and formats can vary depending on your `version.json` settings and version height. + +Property | Example value +--|-- +AssemblyFileVersion | 2.7.74.11627 +AssemblyInformationalVersion | 2.7.74-alpha+6b2d14ba68 +AssemblyVersion | 2.7.0.0 +BuildingRef | refs/heads/fix299 +BuildNumber | 74 +BuildVersion | 2.7.74.11627 +BuildVersion3Components | 2.7.74 +BuildVersionNumberComponent | 74 +BuildVersionSimple | 2.7.74 +ChocolateyPackageVersion | 2.7.74-alpha-g6b2d14ba68 +CloudBuildNumber | (empty except in cloud build) +FileVersion | 2.7.74.11627 +GitCommitDateTicks | 637547960670000000 +GitCommitId | 6b2d14ba6844d2152c48268a8d2c1933759e7229 +GitCommitIdShort | 6b2d14ba68 +GitVersionHeight | 74 +MajorMinorVersion | 2.7 +NPMPackageVersion | 2.7.74-alpha.g6b2d14ba68 +NuGetPackageVersion | 2.7.74-alpha-g6b2d14ba68 +PackageVersion | 2.7.74-alpha-g6b2d14ba68 +PrereleaseVersion | -alpha +PublicRelease | False +SemVerBuildSuffix | +6b2d14ba68 +Version | 2.7.74-alpha-g6b2d14ba68 + ## Build performance Repos with many projects or many commits between major/minor version bumps can suffer from compromised build performance due to the MSBuild task that computes the version information for each project. From c6bc22403965b6336a4afe52d244d796cbc94536 Mon Sep 17 00:00:00 2001 From: "C. Augusto Proiete" Date: Sun, 30 May 2021 15:17:10 -0300 Subject: [PATCH 08/16] Add cake-addin tag to Cake.GitVersioning NuGet package --- src/Cake.GitVersioning/Cake.GitVersioning.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Cake.GitVersioning/Cake.GitVersioning.csproj b/src/Cake.GitVersioning/Cake.GitVersioning.csproj index 62f6dc01..87c9fdc4 100644 --- a/src/Cake.GitVersioning/Cake.GitVersioning.csproj +++ b/src/Cake.GitVersioning/Cake.GitVersioning.csproj @@ -8,7 +8,7 @@ andarno Cake wrapper for Nerdbank.GitVersioning. Stamps your assemblies with semver 2.0 compliant git commit specific version information and provides NuGet versioning information as well. Copyright (c) .NET Foundation and Contributors - git commit versioning version assemblyinfo + git commit versioning version assemblyinfo cake-addin https://cdn.jsdelivr.net/gh/cake-contrib/graphics/png/cake-contrib-medium.png cake-contrib-medium.png http://github.com/dotnet/Nerdbank.GitVersioning From cfcbc7e434c2fe1d5499a31cd7bcc548bad9ad8b Mon Sep 17 00:00:00 2001 From: "C. Augusto Proiete" Date: Sun, 30 May 2021 15:22:25 -0300 Subject: [PATCH 09/16] Update Cake.GitVersioning NuGet package icon to the new icon for Cake addins --- .../Cake.GitVersioning.csproj | 6 +++--- .../cake-contrib-addin-medium.png | Bin 0 -> 15893 bytes src/Cake.GitVersioning/cake-contrib-medium.png | Bin 15580 -> 0 bytes 3 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 src/Cake.GitVersioning/cake-contrib-addin-medium.png delete mode 100644 src/Cake.GitVersioning/cake-contrib-medium.png diff --git a/src/Cake.GitVersioning/Cake.GitVersioning.csproj b/src/Cake.GitVersioning/Cake.GitVersioning.csproj index 62f6dc01..0ae5bc75 100644 --- a/src/Cake.GitVersioning/Cake.GitVersioning.csproj +++ b/src/Cake.GitVersioning/Cake.GitVersioning.csproj @@ -9,8 +9,8 @@ Cake wrapper for Nerdbank.GitVersioning. Stamps your assemblies with semver 2.0 compliant git commit specific version information and provides NuGet versioning information as well. Copyright (c) .NET Foundation and Contributors git commit versioning version assemblyinfo - https://cdn.jsdelivr.net/gh/cake-contrib/graphics/png/cake-contrib-medium.png - cake-contrib-medium.png + https://cdn.jsdelivr.net/gh/cake-contrib/graphics/png/addin/cake-contrib-addin-medium.png + cake-contrib-addin-medium.png http://github.com/dotnet/Nerdbank.GitVersioning false @@ -36,7 +36,7 @@ - + diff --git a/src/Cake.GitVersioning/cake-contrib-addin-medium.png b/src/Cake.GitVersioning/cake-contrib-addin-medium.png new file mode 100644 index 0000000000000000000000000000000000000000..84c2a823c7b1757c9f61013337351de45a309ccc GIT binary patch literal 15893 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 From e9fbae8d46b9b8e28038cb9378682e24e54958a1 Mon Sep 17 00:00:00 2001 From: TrymPet Date: Thu, 3 Jun 2021 15:03:18 +0200 Subject: [PATCH 10/16] Fix spelling error Remove a duplicate word --- doc/public_vs_stable.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/public_vs_stable.md b/doc/public_vs_stable.md index 3c121400..058790e0 100644 --- a/doc/public_vs_stable.md +++ b/doc/public_vs_stable.md @@ -25,7 +25,7 @@ When a branch becomes stable, the `-prerelease` tag can be removed by adding a c To remove the `-prerelease`, the version.json file must be changed to remove it. Committing this change communicates to everyone looking at the repo that this software is stable. -The natural evolution of a product includes usually includes entering and exiting a `-prerelease` stage many times, but within a branded release (usually recognized by an intentional version number like "1.2") the progression usually transitions only one direction: from `-prerelease` to stable quality. +The natural evolution of a product usually includes entering and exiting a `-prerelease` stage many times, but within a branded release (usually recognized by an intentional version number like "1.2") the progression usually transitions only one direction: from `-prerelease` to stable quality. For example, an anticipated version 1.2 might first be released to the public as 1.2-beta before releasing as 1.2 (without the `-beta` suffix). If the product is undergoing significant changes that warrant downgrading the stability rating to pre-release quality, the version number tends to be incremented at the same time. So a 1.2 product's subsequent release might appear as 1.3-beta or 2.0-beta. From e463aab30aae8b5ca6c8641c284c736c8db1f396 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Sun, 13 Jun 2021 21:21:14 -0600 Subject: [PATCH 11/16] Update Microsoft.Net.Compilers.Toolset to 3.10.0 --- src/Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 7f82c288..e283fab8 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -24,7 +24,7 @@ 2.0.312 - + From 6a966c565f04e7b799f04f1cf0c10a668424652a Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Sat, 7 Aug 2021 15:35:04 -0600 Subject: [PATCH 12/16] Rename `GitExtensionsTests` to `LibGit2GitExtensionsTests` This because the test class focuses only on libgit2. --- .../{GitExtensionsTests.cs => LibGit2GitExtensionsTests.cs} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename src/NerdBank.GitVersioning.Tests/{GitExtensionsTests.cs => LibGit2GitExtensionsTests.cs} (99%) diff --git a/src/NerdBank.GitVersioning.Tests/GitExtensionsTests.cs b/src/NerdBank.GitVersioning.Tests/LibGit2GitExtensionsTests.cs similarity index 99% rename from src/NerdBank.GitVersioning.Tests/GitExtensionsTests.cs rename to src/NerdBank.GitVersioning.Tests/LibGit2GitExtensionsTests.cs index 7a8704dc..c6580a7d 100644 --- a/src/NerdBank.GitVersioning.Tests/GitExtensionsTests.cs +++ b/src/NerdBank.GitVersioning.Tests/LibGit2GitExtensionsTests.cs @@ -11,9 +11,9 @@ using Xunit.Abstractions; using Version = System.Version; -public partial class GitExtensionsTests : RepoTestBase +public class LibGit2GitExtensionsTests : RepoTestBase { - public GitExtensionsTests(ITestOutputHelper Logger) + public LibGit2GitExtensionsTests(ITestOutputHelper Logger) : base(Logger) { this.InitializeSourceControl(); From 3272834e568b0e3f8db54b436c58a50cd92f64af Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Sat, 7 Aug 2021 16:03:48 -0600 Subject: [PATCH 13/16] Delete dead code --- .../LibGit2GitExtensionsTests.cs | 16 ------------ .../LibGit2/LibGit2GitExtensions.cs | 26 ------------------- 2 files changed, 42 deletions(-) diff --git a/src/NerdBank.GitVersioning.Tests/LibGit2GitExtensionsTests.cs b/src/NerdBank.GitVersioning.Tests/LibGit2GitExtensionsTests.cs index c6580a7d..7f14277b 100644 --- a/src/NerdBank.GitVersioning.Tests/LibGit2GitExtensionsTests.cs +++ b/src/NerdBank.GitVersioning.Tests/LibGit2GitExtensionsTests.cs @@ -166,22 +166,6 @@ public void GetVersionHeight_ProgressAndReset(string version1, string version2, Assert.Equal(!versionHeightReset, height2 > height1); } - [Fact] - public void GetTruncatedCommitIdAsInteger_Roundtrip() - { - var firstCommit = this.LibGit2Repository.Commit("First", this.Signer, this.Signer, new CommitOptions { AllowEmptyCommit = true }); - var secondCommit = this.LibGit2Repository.Commit("Second", this.Signer, this.Signer, new CommitOptions { AllowEmptyCommit = true }); - - int id1 = firstCommit.GetTruncatedCommitIdAsInt32(); - int id2 = secondCommit.GetTruncatedCommitIdAsInt32(); - - this.Logger.WriteLine($"Commit {firstCommit.Id.Sha.Substring(0, 8)} as int: {id1}"); - this.Logger.WriteLine($"Commit {secondCommit.Id.Sha.Substring(0, 8)} as int: {id2}"); - - Assert.Equal(firstCommit, this.LibGit2Repository.GetCommitFromTruncatedIdInteger(id1)); - Assert.Equal(secondCommit, this.LibGit2Repository.GetCommitFromTruncatedIdInteger(id2)); - } - [Fact] public void GetIdAsVersion_ReadsMajorMinorFromVersionTxt() { diff --git a/src/NerdBank.GitVersioning/LibGit2/LibGit2GitExtensions.cs b/src/NerdBank.GitVersioning/LibGit2/LibGit2GitExtensions.cs index 3d17c5f6..9dabdbb2 100644 --- a/src/NerdBank.GitVersioning/LibGit2/LibGit2GitExtensions.cs +++ b/src/NerdBank.GitVersioning/LibGit2/LibGit2GitExtensions.cs @@ -97,18 +97,6 @@ public static int GetHeight(LibGit2Context context, Func? continue return GetCommitHeight(context.Commit, tracker, continueStepping); } - /// - /// Takes the first 4 bytes of a commit ID (i.e. first 8 characters of its hex-encoded SHA) - /// and returns them as an integer. - /// - /// The commit to identify with an integer. - /// The integer which identifies a commit. - public static int GetTruncatedCommitIdAsInt32(this Commit commit) - { - Requires.NotNull(commit, nameof(commit)); - return BitConverter.ToInt32(commit.Id.RawId, 0); - } - /// /// Takes the first 2 bytes of a commit ID (i.e. first 4 characters of its hex-encoded SHA) /// and returns them as an 16-bit unsigned integer. @@ -121,20 +109,6 @@ public static ushort GetTruncatedCommitIdAsUInt16(this Commit commit) return BitConverter.ToUInt16(commit.Id.RawId, 0); } - /// - /// Looks up a commit by an integer that captures the first for bytes of its ID. - /// - /// The repo to search for a matching commit. - /// The value returned from . - /// A matching commit. - public static Commit GetCommitFromTruncatedIdInteger(this Repository repo, int truncatedId) - { - Requires.NotNull(repo, nameof(repo)); - - byte[] rawId = BitConverter.GetBytes(truncatedId); - return repo.Lookup(EncodeAsHex(rawId)); - } - /// /// Returns the repository that belongs to. /// From 6668ac9259773d5dd4e42ced04d4676a919746e6 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Sat, 7 Aug 2021 16:04:50 -0600 Subject: [PATCH 14/16] Always decode the first two bytes of a commit ID into `ushort` as big endian This fixes a non-deterministic version computation that varied based on endianness of the processor. Most computers use little-endian, which produced a decimal version that when converted back to hex with a typical calculator would have the first two commit ID bytes in swapped positions. Now with this change, we "fix" the endianness. We choose big endian since it won't swap the first two bytes like little endian did. But this presents another problem: all the generated versions now have a different value for the 4th integer component, and `nbgv get-commits` will no longer match a commit when it built using the little-endian version of NB.GV. I'll fix this in a subsequent commit so that this CLI tool will match on commits allowing the order to be swapped. Fixes #637 --- .../ManagedGit/GitObjectIdTests.cs | 2 +- .../VersionOracleTests.cs | 20 +++++++++++++++++++ .../LibGit2/LibGit2GitExtensions.cs | 6 +++--- .../ManagedGit/GitObjectId.cs | 2 +- 4 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/NerdBank.GitVersioning.Tests/ManagedGit/GitObjectIdTests.cs b/src/NerdBank.GitVersioning.Tests/ManagedGit/GitObjectIdTests.cs index c06d8f67..baeb4ff7 100644 --- a/src/NerdBank.GitVersioning.Tests/ManagedGit/GitObjectIdTests.cs +++ b/src/NerdBank.GitVersioning.Tests/ManagedGit/GitObjectIdTests.cs @@ -93,7 +93,7 @@ public void AsUInt16Test() { // The hash code is the int32 representation of the first 4 bytes var objectId = GitObjectId.ParseHex(this.shaAsHexAsciiByteArray); - Assert.Equal(0x914e, objectId.AsUInt16()); + Assert.Equal(0x4e91, objectId.AsUInt16()); Assert.Equal(0, GitObjectId.Empty.GetHashCode()); } diff --git a/src/NerdBank.GitVersioning.Tests/VersionOracleTests.cs b/src/NerdBank.GitVersioning.Tests/VersionOracleTests.cs index 4f10abf1..7d992920 100644 --- a/src/NerdBank.GitVersioning.Tests/VersionOracleTests.cs +++ b/src/NerdBank.GitVersioning.Tests/VersionOracleTests.cs @@ -845,6 +845,26 @@ public void GitCommitIdShort() } } + [Fact] + public void GitCommidIdLeading16BitsDecodedWithBigEndian() + { + this.WriteVersionFile(new VersionOptions { Version = SemanticVersion.Parse("1.2"), GitCommitIdShortAutoMinimum = 4 }); + this.InitializeSourceControl(); + this.AddCommits(1); + var oracle = new VersionOracle(this.Context); + + string leadingFourChars = this.Context.GitCommitId.Substring(0, 4); + ushort expectedNumber = FromHex(leadingFourChars); + ushort actualNumber = checked((ushort)oracle.Version.Revision); + this.Logger.WriteLine("First two characters from commit ID in hex is {0}", leadingFourChars); + this.Logger.WriteLine("First two characters, converted to a number is {0}", expectedNumber); + this.Logger.WriteLine("Generated 16-bit ushort from commit ID is {0}, whose hex representation is {1}", actualNumber, ToHex(actualNumber)); + Assert.Equal(expectedNumber, actualNumber); + + static string ToHex(ushort number) => number.ToString("X"); + static ushort FromHex(string hex) => ushort.Parse(hex, System.Globalization.NumberStyles.HexNumber); + } + [Fact(Skip = "Slow test")] public void GetVersionHeight_VeryLongHistory() { diff --git a/src/NerdBank.GitVersioning/LibGit2/LibGit2GitExtensions.cs b/src/NerdBank.GitVersioning/LibGit2/LibGit2GitExtensions.cs index 9dabdbb2..a0b46df1 100644 --- a/src/NerdBank.GitVersioning/LibGit2/LibGit2GitExtensions.cs +++ b/src/NerdBank.GitVersioning/LibGit2/LibGit2GitExtensions.cs @@ -3,8 +3,8 @@ namespace Nerdbank.GitVersioning.LibGit2 { using System; + using System.Buffers.Binary; using System.Collections.Generic; - using System.Globalization; using System.IO; using System.Linq; using System.Runtime.InteropServices; @@ -106,7 +106,7 @@ public static int GetHeight(LibGit2Context context, Func? continue public static ushort GetTruncatedCommitIdAsUInt16(this Commit commit) { Requires.NotNull(commit, nameof(commit)); - return BitConverter.ToUInt16(commit.Id.RawId, 0); + return BinaryPrimitives.ReadUInt16BigEndian(commit.Id.RawId); } /// @@ -301,7 +301,7 @@ private static bool IsCommitIdMismatch(Version version, VersionOptions versionOp /// True if the object's ID starts with after applying the . private static bool StartsWith(this ObjectId @object, ushort leadingBytes, ushort bitMask = 0xffff) { - ushort truncatedObjectId = BitConverter.ToUInt16(@object.RawId, 0); + ushort truncatedObjectId = BinaryPrimitives.ReadUInt16BigEndian(@object.RawId); return (truncatedObjectId & bitMask) == leadingBytes; } diff --git a/src/NerdBank.GitVersioning/ManagedGit/GitObjectId.cs b/src/NerdBank.GitVersioning/ManagedGit/GitObjectId.cs index b18d04a9..f21794b7 100644 --- a/src/NerdBank.GitVersioning/ManagedGit/GitObjectId.cs +++ b/src/NerdBank.GitVersioning/ManagedGit/GitObjectId.cs @@ -167,7 +167,7 @@ public override bool Equals(object? obj) /// /// A which represents the first two bytes of this . /// - public ushort AsUInt16() => BinaryPrimitives.ReadUInt16LittleEndian(this.Value.Slice(0, 2)); + public ushort AsUInt16() => BinaryPrimitives.ReadUInt16BigEndian(this.Value.Slice(0, 2)); /// /// Returns the SHA1 hash of this object. From de6ca295bb382fea61bd0760236fdd6f4bcb1bdd Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Sat, 7 Aug 2021 20:28:50 -0600 Subject: [PATCH 15/16] Match commits based on versions that used either endian to calculate --- .../LibGit2GitExtensionsTests.cs | 14 ++++++++++++++ src/NerdBank.GitVersioning.Tests/TestUtilities.cs | 4 ++++ .../VersionOracleTests.cs | 7 ++----- .../LibGit2/LibGit2GitExtensions.cs | 11 ++++++++--- 4 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/NerdBank.GitVersioning.Tests/LibGit2GitExtensionsTests.cs b/src/NerdBank.GitVersioning.Tests/LibGit2GitExtensionsTests.cs index 7f14277b..b01ce4da 100644 --- a/src/NerdBank.GitVersioning.Tests/LibGit2GitExtensionsTests.cs +++ b/src/NerdBank.GitVersioning.Tests/LibGit2GitExtensionsTests.cs @@ -1,4 +1,5 @@ using System; +using System.Buffers.Binary; using System.Collections.Generic; using System.Diagnostics; using System.IO; @@ -368,6 +369,19 @@ public void GetIdAsVersion_Roundtrip_UnstableOffset(int startingOffset, int offs } } + [Fact] + public void GetCommitsFromVersion_MatchesOnEitherEndian() + { + this.InitializeSourceControl(); + Commit commit = this.WriteVersionFile(new VersionOptions { Version = SemanticVersion.Parse("1.2"), GitCommitIdShortAutoMinimum = 4 }); + + Version originalVersion = new VersionOracle(this.Context).Version; + Version swappedEndian = new Version(originalVersion.Major, originalVersion.Minor, originalVersion.Build, BinaryPrimitives.ReverseEndianness((ushort)originalVersion.Revision)); + ushort twoBytesFromCommitId = checked((ushort)originalVersion.Revision); + Assert.Contains(commit, LibGit2GitExtensions.GetCommitsFromVersion(this.Context, originalVersion)); + Assert.Contains(commit, LibGit2GitExtensions.GetCommitsFromVersion(this.Context, swappedEndian)); + } + [Fact] public void GetIdAsVersion_Roundtrip_WithSubdirectoryVersionFiles() { diff --git a/src/NerdBank.GitVersioning.Tests/TestUtilities.cs b/src/NerdBank.GitVersioning.Tests/TestUtilities.cs index a67edbd1..cad5242a 100644 --- a/src/NerdBank.GitVersioning.Tests/TestUtilities.cs +++ b/src/NerdBank.GitVersioning.Tests/TestUtilities.cs @@ -79,6 +79,10 @@ internal static ExpandedRepo ExtractRepoArchive(string repoArchiveName) } } + internal static string ToHex(ushort number) => number.ToString("X"); + + internal static ushort FromHex(string hex) => ushort.Parse(hex, System.Globalization.NumberStyles.HexNumber); + internal class ExpandedRepo : IDisposable { internal ExpandedRepo(string repoPath) diff --git a/src/NerdBank.GitVersioning.Tests/VersionOracleTests.cs b/src/NerdBank.GitVersioning.Tests/VersionOracleTests.cs index 7d992920..1e0fc51f 100644 --- a/src/NerdBank.GitVersioning.Tests/VersionOracleTests.cs +++ b/src/NerdBank.GitVersioning.Tests/VersionOracleTests.cs @@ -854,15 +854,12 @@ public void GitCommidIdLeading16BitsDecodedWithBigEndian() var oracle = new VersionOracle(this.Context); string leadingFourChars = this.Context.GitCommitId.Substring(0, 4); - ushort expectedNumber = FromHex(leadingFourChars); + ushort expectedNumber = TestUtilities.FromHex(leadingFourChars); ushort actualNumber = checked((ushort)oracle.Version.Revision); this.Logger.WriteLine("First two characters from commit ID in hex is {0}", leadingFourChars); this.Logger.WriteLine("First two characters, converted to a number is {0}", expectedNumber); - this.Logger.WriteLine("Generated 16-bit ushort from commit ID is {0}, whose hex representation is {1}", actualNumber, ToHex(actualNumber)); + this.Logger.WriteLine("Generated 16-bit ushort from commit ID is {0}, whose hex representation is {1}", actualNumber, TestUtilities.ToHex(actualNumber)); Assert.Equal(expectedNumber, actualNumber); - - static string ToHex(ushort number) => number.ToString("X"); - static ushort FromHex(string hex) => ushort.Parse(hex, System.Globalization.NumberStyles.HexNumber); } [Fact(Skip = "Slow test")] diff --git a/src/NerdBank.GitVersioning/LibGit2/LibGit2GitExtensions.cs b/src/NerdBank.GitVersioning/LibGit2/LibGit2GitExtensions.cs index a0b46df1..aa27910b 100644 --- a/src/NerdBank.GitVersioning/LibGit2/LibGit2GitExtensions.cs +++ b/src/NerdBank.GitVersioning/LibGit2/LibGit2GitExtensions.cs @@ -284,7 +284,11 @@ private static bool IsCommitIdMismatch(Version version, VersionOptions versionOp ushort objectIdLeadingValue = (ushort)expectedCommitIdLeadingValue; ushort objectIdMask = (ushort)(objectIdLeadingValue == MaximumBuildNumberOrRevisionComponent ? 0xfffe : 0xffff); - return !commit.Id.StartsWith(objectIdLeadingValue, objectIdMask); + // Accept a big endian match or a little endian match. + // Nerdbank.GitVersioning up to v3.4 would produce versions based on the endianness of the CPU it ran on (typically little endian). + // Starting with v3.5, it deterministically used big endian. In order for `nbgv get-commits` to match on versions computed before and after the change, + // we match on either endian setting. + return !(commit.Id.StartsWith(objectIdLeadingValue, bigEndian: true, objectIdMask) || commit.Id.StartsWith(objectIdLeadingValue, bigEndian: false, objectIdMask)); } } @@ -298,10 +302,11 @@ private static bool IsCommitIdMismatch(Version version, VersionOptions versionOp /// The object whose ID is to be tested. /// The leading 16-bits to be tested. /// The mask that indicates which bits should be compared. + /// to read the first two bytes as big endian (v3.5+ behavior); to use little endian (v3.4 and earlier behavior). /// True if the object's ID starts with after applying the . - private static bool StartsWith(this ObjectId @object, ushort leadingBytes, ushort bitMask = 0xffff) + private static bool StartsWith(this ObjectId @object, ushort leadingBytes, bool bigEndian, ushort bitMask = 0xffff) { - ushort truncatedObjectId = BinaryPrimitives.ReadUInt16BigEndian(@object.RawId); + ushort truncatedObjectId = bigEndian ? BinaryPrimitives.ReadUInt16BigEndian(@object.RawId) : BinaryPrimitives.ReadUInt16LittleEndian(@object.RawId); return (truncatedObjectId & bitMask) == leadingBytes; } From 5789043fc06d0dd078a52c2e38b2e42c7839199a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Aug 2021 22:33:00 -0600 Subject: [PATCH 16/16] Bump path-parse from 1.0.6 to 1.0.7 in /src/nerdbank-gitversioning.npm (#641) Bumps [path-parse](https://github.com/jbgutierrez/path-parse) from 1.0.6 to 1.0.7. - [Release notes](https://github.com/jbgutierrez/path-parse/releases) - [Commits](https://github.com/jbgutierrez/path-parse/commits/v1.0.7) --- updated-dependencies: - dependency-name: path-parse dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/nerdbank-gitversioning.npm/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/nerdbank-gitversioning.npm/yarn.lock b/src/nerdbank-gitversioning.npm/yarn.lock index 5d2beb75..c66da78b 100644 --- a/src/nerdbank-gitversioning.npm/yarn.lock +++ b/src/nerdbank-gitversioning.npm/yarn.lock @@ -2029,9 +2029,9 @@ path-is-absolute@^1.0.0: integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= path-parse@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" - integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== path-root-regex@^0.1.0: version "0.1.2"