public void PrepareRelease_JsonOutputWhenUpdatingReleaseBranch() { // create and configure repository this.InitializeSourceControl(); // create version.json var versionOptions = new VersionOptions() { Version = SemanticVersion.Parse("1.0"), Release = new ReleaseOptions() { BranchName = "v{version}", VersionIncrement = ReleaseVersionIncrement.Minor } }; this.WriteVersionFile(versionOptions); var branchName = "v1.0"; // switch to release branch Commands.Checkout(this.Repo, this.Repo.CreateBranch(branchName)); // run release preparation var stdout = new StringWriter(); var releaseManager = new ReleaseManager(stdout); releaseManager.PrepareRelease(this.RepoPath, outputMode: ReleaseManager.ReleaseManagerOutputMode.Json); // Expected output: // { // "CurrentBranch" : { // "Name" : "<NAME>", // "Commit" : "<COMMIT>", // "Version" : "<VERSION>", // }, // "NewBranch" : null // } var jsonOutput = JObject.Parse(stdout.ToString()); // check "CurrentBranch" output { var expectedCommitId = this.Repo.Branches[branchName].Tip.Sha; var expectedVersion = VersionFile.GetVersion(this.Repo.Branches[branchName].Tip).Version.ToString(); var currentBranchOutput = jsonOutput.Property("CurrentBranch")?.Value as JObject; Assert.NotNull(currentBranchOutput); Assert.Equal(branchName, currentBranchOutput.GetValue("Name")?.ToString()); Assert.Equal(expectedCommitId, currentBranchOutput.GetValue("Commit")?.ToString()); Assert.Equal(expectedVersion, currentBranchOutput.GetValue("Version")?.ToString()); } // Check "NewBranch" output { // no new branch was created, so "NewBranch" should be null var newBranchOutput = jsonOutput.Property("NewBranch")?.Value as JObject; Assert.Null(newBranchOutput); } }
public void SetVersion_PathFilters_InheritRelativePaths() { this.InitializeSourceControl(); var rootVersionOptions = new VersionOptions { Version = SemanticVersion.Parse("1.2"), PathFilters = new [] { new FilterPath("./root-file.txt", ""), new FilterPath("/absolute", ""), } }; VersionFile.SetVersion(this.RepoPath, rootVersionOptions); var versionOptions = new VersionOptions { Version = SemanticVersion.Parse("1.2"), Inherit = true }; var projectDirectory = Path.Combine(this.RepoPath, "quux"); VersionFile.SetVersion(projectDirectory, versionOptions); var expected = rootVersionOptions.PathFilters.Select(x => x.RepoRelativePath).ToList(); var actualVersionOptions = VersionFile.GetVersion(projectDirectory); var actual = actualVersionOptions.PathFilters.Select(x => x.RepoRelativePath).ToList(); Assert.Equal(expected, actual); }
public void GetVersion_ThrowsWithPathFiltersOutsideOfGitRepo() { var json = @"{ ""version"" : ""1.2"", ""pathFilters"" : [ ""."" ] }"; var path = Path.Combine(this.RepoPath, "version.json"); File.WriteAllText(path, json); Assert.Throws <ArgumentNullException>(() => VersionFile.GetVersion(this.RepoPath)); }
public void GetVersion_CanReadSpecConformantJsonFile() { File.WriteAllText(Path.Combine(this.RepoPath, VersionFile.JsonFileName), "{ version: \"1.2-pre\" }"); VersionOptions actualVersion = VersionFile.GetVersion(this.RepoPath); Assert.NotNull(actualVersion); Assert.Equal(new Version(1, 2), actualVersion.Version.Version); Assert.Equal("-pre", actualVersion.Version.Prerelease); }
public void GetVersion_CanReadSpecConformantTxtFile_MultiLineNoHyphen() { File.WriteAllText(Path.Combine(this.RepoPath, VersionFile.TxtFileName), "1.2\npre"); VersionOptions actualVersion = VersionFile.GetVersion(this.RepoPath); Assert.NotNull(actualVersion); Assert.Equal(new Version(1, 2), actualVersion.Version.Version); Assert.Equal("-pre", actualVersion.Version.Prerelease); }
public void PrepareRelease_ReleaseBranch(string initialVersion, string releaseOptionsBranchName, string releaseUnstableTag, string releaseBranchName, string resultingVersion) { releaseOptionsBranchName = releaseOptionsBranchName ?? new ReleaseOptions().BranchNameOrDefault; // create and configure repository this.InitializeSourceControl(); this.Repo.Config.Set("user.name", this.Signer.Name, ConfigurationLevel.Local); this.Repo.Config.Set("user.email", this.Signer.Email, ConfigurationLevel.Local); var initialVersionOptions = new VersionOptions() { Version = SemanticVersion.Parse(initialVersion), Release = new ReleaseOptions() { BranchName = releaseOptionsBranchName } }; var expectedVersionOptions = new VersionOptions() { Version = SemanticVersion.Parse(resultingVersion), Release = new ReleaseOptions() { BranchName = releaseOptionsBranchName } }; // create version.json this.WriteVersionFile(initialVersionOptions); // switch to release branch var branchName = releaseBranchName; Commands.Checkout(this.Repo, this.Repo.CreateBranch(branchName)); var tipBeforePrepareRelease = this.Repo.Head.Tip; // run PrepareRelease var releaseManager = new ReleaseManager(); releaseManager.PrepareRelease(this.RepoPath, releaseUnstableTag); // Check if a commit was created { var updateVersionCommit = this.Repo.Head.Tip; Assert.NotEqual(tipBeforePrepareRelease.Id, updateVersionCommit.Id); Assert.Single(updateVersionCommit.Parents); Assert.Equal(updateVersionCommit.Parents.Single().Id, tipBeforePrepareRelease.Id); } // check version on release branch { var actualVersionOptions = VersionFile.GetVersion(this.Repo.Branches[branchName].Tip); Assert.Equal(expectedVersionOptions, actualVersionOptions); } }
public void VersionJson_InheritButNoParentFileFound() { this.InitializeSourceControl(); this.WriteVersionFile( new VersionOptions { Inherit = true, Version = SemanticVersion.Parse("14.2"), }); Assert.Throws <InvalidOperationException>(() => VersionFile.GetVersion(this.Repo)); }
public void GetVersion_Commit() { Assert.Null(VersionFile.GetVersion((Commit)null)); this.InitializeSourceControl(); this.WriteVersionFile(); VersionOptions fromCommit = VersionFile.GetVersion(this.Repo.Head.Commits.First()); VersionOptions fromFile = VersionFile.GetVersion(this.RepoPath); Assert.NotNull(fromCommit); Assert.Equal(fromFile, fromCommit); }
public void GetVersion_ReadPathFilters() { var json = @"{ ""version"" : ""1.2"", ""pathFilters"" : [ "":/root.txt"", ""./hello"" ] }"; var path = Path.Combine(this.RepoPath, "version.json"); File.WriteAllText(path, json); var versionOptions = VersionFile.GetVersion(this.RepoPath); Assert.NotNull(versionOptions.PathFilters); Assert.Equal(new[] { ":/root.txt", "./hello" }, versionOptions.PathFilters); }
private void AssertPathHasVersion(Commit commit, string absolutePath, VersionOptions expected) { var actual = VersionFile.GetVersion(absolutePath); Assert.Equal(expected, actual); // Pass in the repo-relative path to ensure the commit is used as the data source. string relativePath = absolutePath.Substring(this.RepoPath.Length).TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); actual = VersionFile.GetVersion(commit, relativePath); Assert.Equal(expected, actual); }
public void GetVersion_ReadReleaseSettings_BranchName() { var json = @"{ ""version"" : ""1.2"", ""release"" : { ""branchName"" : ""someValue{version}"" } }"; var path = Path.Combine(this.RepoPath, "version.json"); File.WriteAllText(path, json); var versionOptions = VersionFile.GetVersion(this.RepoPath); Assert.NotNull(versionOptions.Release); Assert.NotNull(versionOptions.Release.BranchName); Assert.Equal("someValue{version}", versionOptions.Release.BranchName); }
public void GetVersion_ReadReleaseSettings_FirstUnstableTag() { var json = @"{ ""version"" : ""1.2"", ""release"" : { ""firstUnstableTag"" : ""preview"" } }"; var path = Path.Combine(this.RepoPath, "version.json"); File.WriteAllText(path, json); var versionOptions = VersionFile.GetVersion(this.RepoPath); Assert.NotNull(versionOptions.Release); Assert.NotNull(versionOptions.Release.FirstUnstableTag); Assert.Equal("preview", versionOptions.Release.FirstUnstableTag); }
public void GetVersion_ReadReleaseSettings_VersionIncrement() { var json = @"{ ""version"" : ""1.2"", ""release"" : { ""versionIncrement"" : ""major"" } }"; var path = Path.Combine(this.RepoPath, "version.json"); File.WriteAllText(path, json); var versionOptions = VersionFile.GetVersion(this.RepoPath); Assert.NotNull(versionOptions.Release); Assert.NotNull(versionOptions.Release.VersionIncrement); Assert.Equal(VersionOptions.ReleaseVersionIncrement.Major, versionOptions.Release.VersionIncrement); }
public void GetVersion_JsonCompatibility(string version, string assemblyVersion, object precision, int versionHeightOffset, string[] publicReleaseRefSpec, string json) { File.WriteAllText(Path.Combine(this.RepoPath, VersionFile.JsonFileName), json); var options = VersionFile.GetVersion(this.RepoPath); Assert.NotNull(options); Assert.Equal(version, options.Version?.ToString()); Assert.Equal(assemblyVersion, options.AssemblyVersion?.Version?.ToString()); Assert.Equal(precision, options.AssemblyVersion?.PrecisionOrDefault); Assert.Equal(versionHeightOffset, options.VersionHeightOffsetOrDefault); Assert.Equal(publicReleaseRefSpec, options.PublicReleaseRefSpec); }
public void SetVersion_GetVersionFromFile(string expectedVersion, string expectedPrerelease) { string pathWritten = VersionFile.SetVersion(this.RepoPath, new Version(expectedVersion), expectedPrerelease); Assert.Equal(Path.Combine(this.RepoPath, VersionFile.JsonFileName), pathWritten); string actualFileContent = File.ReadAllText(pathWritten); this.Logger.WriteLine(actualFileContent); VersionOptions actualVersion = VersionFile.GetVersion(this.RepoPath); Assert.Equal(new Version(expectedVersion), actualVersion.Version.Version); Assert.Equal(expectedPrerelease ?? string.Empty, actualVersion.Version.Prerelease); }
public void GetVersion_ReadPathFilters() { this.InitializeSourceControl(); var json = @"{ ""version"" : ""1.2"", ""pathFilters"" : [ "":/root.txt"", ""./hello"" ] }"; var path = Path.Combine(this.RepoPath, "version.json"); File.WriteAllText(path, json); var repoRelativeBaseDirectory = "."; var versionOptions = VersionFile.GetVersion(this.RepoPath); Assert.NotNull(versionOptions.PathFilters); Assert.Equal(new[] { "/root.txt", "./hello" }, versionOptions.PathFilters.Select(fp => fp.ToPathSpec(repoRelativeBaseDirectory))); }
private static ExitCodes OnSetVersionCommand(string projectPath, string version) { if (!SemanticVersion.TryParse(string.IsNullOrEmpty(version) ? DefaultVersionSpec : version, out var semver)) { Console.Error.WriteLine($"\"{version}\" is not a semver-compliant version spec."); return(ExitCodes.InvalidVersionSpec); } var defaultOptions = new VersionOptions { Version = semver, }; string searchPath = GetSpecifiedOrCurrentDirectoryPath(projectPath); var repository = GitExtensions.OpenGitRepo(searchPath); var existingOptions = VersionFile.GetVersion(searchPath, out string actualDirectory); string versionJsonPath; if (existingOptions != null) { existingOptions.Version = semver; versionJsonPath = VersionFile.SetVersion(actualDirectory, existingOptions); } else if (string.IsNullOrEmpty(projectPath)) { if (repository == null) { Console.Error.WriteLine("No version file and no git repo found at or above: \"{0}\"", searchPath); return(ExitCodes.NoGitRepo); } versionJsonPath = VersionFile.SetVersion(repository.Info.WorkingDirectory, defaultOptions); } else { versionJsonPath = VersionFile.SetVersion(projectPath, defaultOptions); } if (repository != null) { LibGit2Sharp.Commands.Stage(repository, versionJsonPath); } return(ExitCodes.OK); }
public void SetVersion_GetVersionFromFile(string expectedVersion, string expectedPrerelease) { string pathWritten = VersionFile.SetVersion(this.RepoPath, new Version(expectedVersion), expectedPrerelease); Assert.Equal(Path.Combine(this.RepoPath, VersionFile.FileName), pathWritten); string[] actualFileContent = File.ReadAllLines(this.versionTxtPath); this.Logger.WriteLine(string.Join(Environment.NewLine, actualFileContent)); Assert.Equal(2, actualFileContent.Length); Assert.Equal(expectedVersion, actualFileContent[0]); Assert.Equal(expectedPrerelease ?? string.Empty, actualFileContent[1]); SemanticVersion actualVersion = VersionFile.GetVersion(this.RepoPath); Assert.Equal(new Version(expectedVersion), actualVersion.Version); Assert.Equal(expectedPrerelease ?? string.Empty, actualVersion.UnstableTag); }
public void PrepareRelease_ResetsVersionHeightOffset() { // create and configure repository this.InitializeSourceControl(); var initialVersionOptions = new VersionOptions() { Version = SemanticVersion.Parse("1.0-beta"), VersionHeightOffset = 5, }; var expectedReleaseVersionOptions = new VersionOptions() { Version = SemanticVersion.Parse("1.0"), VersionHeightOffset = 5, }; var expectedMainVersionOptions = new VersionOptions() { Version = SemanticVersion.Parse("1.1-alpha"), }; // create version.json this.WriteVersionFile(initialVersionOptions); var tipBeforePrepareRelease = this.Repo.Head.Tip; var releaseManager = new ReleaseManager(); releaseManager.PrepareRelease(this.RepoPath); var newVersion = VersionFile.GetVersion(this.RepoPath); Assert.Equal(expectedMainVersionOptions, newVersion); var releaseVersion = VersionFile.GetVersion(this.Repo.Branches["v1.0"].Tip); Assert.Equal(expectedReleaseVersionOptions, releaseVersion); }
public void PrepareRelease_JsonOutput() { // create and configure repository this.InitializeSourceControl(); // create version.json var versionOptions = new VersionOptions() { Version = SemanticVersion.Parse("1.0"), Release = new ReleaseOptions() { BranchName = "v{version}", VersionIncrement = ReleaseVersionIncrement.Minor } }; this.WriteVersionFile(versionOptions); var currentBranchName = this.Repo.Head.FriendlyName; var releaseBranchName = "v1.0"; // run release preparation var stdout = new StringWriter(); var releaseManager = new ReleaseManager(stdout); releaseManager.PrepareRelease(this.RepoPath, outputMode: ReleaseManager.ReleaseManagerOutputMode.Json); // Expected output: // { // "CurrentBranch" : { // "Name" : "<NAME-OF-CURRENT-BRANCH>", // "Commit" : "<HEAD-COMMIT-OF-CURRENT-BRANCH>", // "Version" : "<UPDATED-VERSION-ON-CURRENT-BRANCH>", // }, // "NewBranch" : { // "Name" : "<NAME-OF-CREATED-BRANCH>", // "Commit" : "<HEAD-COMMIT-OF-CREATED-BRANCH>", // "Version" : "<VERSION-ON-CREATED-BRANCH>", // } // } var jsonOutput = JObject.Parse(stdout.ToString()); // check "CurrentBranch" output { var expectedCommitId = this.Repo.Branches[currentBranchName].Tip.Sha; var expectedVersion = VersionFile.GetVersion(this.Repo.Branches[currentBranchName].Tip).Version.ToString(); var currentBranchOutput = jsonOutput.Property("CurrentBranch")?.Value as JObject; Assert.NotNull(currentBranchOutput); Assert.Equal(currentBranchName, currentBranchOutput.GetValue("Name")?.ToString()); Assert.Equal(expectedCommitId, currentBranchOutput.GetValue("Commit")?.ToString()); Assert.Equal(expectedVersion, currentBranchOutput.GetValue("Version")?.ToString()); } // Check "NewBranch" output { var expectedCommitId = this.Repo.Branches[releaseBranchName].Tip.Sha; var expectedVersion = VersionFile.GetVersion(this.Repo.Branches[releaseBranchName].Tip).Version.ToString(); var newBranchOutput = jsonOutput.Property("NewBranch")?.Value as JObject; Assert.NotNull(newBranchOutput); Assert.Equal(releaseBranchName, newBranchOutput.GetValue("Name")?.ToString()); Assert.Equal(expectedCommitId, newBranchOutput.GetValue("Commit")?.ToString()); Assert.Equal(expectedVersion, newBranchOutput.GetValue("Version")?.ToString()); } }
public void PrepareRelease_Master( // data for initial setup (version and release options configured in version.json) string initialVersion, string releaseOptionsBranchName, ReleaseVersionIncrement?releaseOptionsVersionIncrement, string releaseOptionsFirstUnstableTag, // arguments passed to PrepareRelease() string releaseUnstableTag, string nextVersion, ReleaseVersionIncrement?parameterVersionIncrement, // expected versions and branch name after running PrepareRelease() string expectedBranchName, string resultingReleaseVersion, string resultingMainVersion) { // create and configure repository this.InitializeSourceControl(); this.Repo.Config.Set("user.name", this.Signer.Name, ConfigurationLevel.Local); this.Repo.Config.Set("user.email", this.Signer.Email, ConfigurationLevel.Local); // create version.json var initialVersionOptions = new VersionOptions() { Version = SemanticVersion.Parse(initialVersion), Release = new ReleaseOptions() { VersionIncrement = releaseOptionsVersionIncrement, BranchName = releaseOptionsBranchName, FirstUnstableTag = releaseOptionsFirstUnstableTag } }; this.WriteVersionFile(initialVersionOptions); var expectedVersionOptionsReleaseBranch = new VersionOptions() { Version = SemanticVersion.Parse(resultingReleaseVersion), Release = new ReleaseOptions() { VersionIncrement = releaseOptionsVersionIncrement, BranchName = releaseOptionsBranchName, FirstUnstableTag = releaseOptionsFirstUnstableTag } }; var expectedVersionOptionsCurrentBrach = new VersionOptions() { Version = SemanticVersion.Parse(resultingMainVersion), Release = new ReleaseOptions() { VersionIncrement = releaseOptionsVersionIncrement, BranchName = releaseOptionsBranchName, FirstUnstableTag = releaseOptionsFirstUnstableTag } }; var initialBranchName = this.Repo.Head.FriendlyName; var tipBeforePrepareRelease = this.Repo.Head.Tip; // prepare release var releaseManager = new ReleaseManager(); releaseManager.PrepareRelease(this.RepoPath, releaseUnstableTag, (nextVersion == null ? null : Version.Parse(nextVersion)), parameterVersionIncrement); // check if a branch was created Assert.Contains(this.Repo.Branches, branch => branch.FriendlyName == expectedBranchName); // PrepareRelease should switch back to the initial branch Assert.Equal(initialBranchName, this.Repo.Head.FriendlyName); // check if release branch contains a new commit // parent of new commit must be the commit before preparing the release var releaseBranch = this.Repo.Branches[expectedBranchName]; { // If the original branch had no -prerelease tag, the release branch has no commit to author. if (string.IsNullOrEmpty(initialVersionOptions.Version.Prerelease)) { Assert.Equal(releaseBranch.Tip.Id, tipBeforePrepareRelease.Id); } else { Assert.NotEqual(releaseBranch.Tip.Id, tipBeforePrepareRelease.Id); Assert.Equal(releaseBranch.Tip.Parents.Single().Id, tipBeforePrepareRelease.Id); } } if (string.IsNullOrEmpty(initialVersionOptions.Version.Prerelease)) { // Verify that one commit was authored. var incrementCommit = this.Repo.Head.Tip; Assert.Single(incrementCommit.Parents); Assert.Equal(tipBeforePrepareRelease.Id, incrementCommit.Parents.Single().Id); } else { // check if current branch contains new commits // - one commit that updates the version (parent must be the commit before preparing the release) // - one commit merging the release branch back to master and resolving the conflict var mergeCommit = this.Repo.Head.Tip; Assert.Equal(2, mergeCommit.Parents.Count()); Assert.Equal(releaseBranch.Tip.Id, mergeCommit.Parents.Skip(1).First().Id); var updateVersionCommit = mergeCommit.Parents.First(); Assert.Single(updateVersionCommit.Parents); Assert.Equal(tipBeforePrepareRelease.Id, updateVersionCommit.Parents.First().Id); } // check version on release branch { var releaseBranchVersion = VersionFile.GetVersion(releaseBranch.Tip); Assert.Equal(expectedVersionOptionsReleaseBranch, releaseBranchVersion); } // check version on master branch { var currentBranchVersion = VersionFile.GetVersion(this.Repo.Head.Tip); Assert.Equal(expectedVersionOptionsCurrentBrach, currentBranchVersion); } }
private static ExitCodes OnInstallCommand(string versionJsonRoot, string version, IReadOnlyList <string> sources) { if (!SemanticVersion.TryParse(string.IsNullOrEmpty(version) ? DefaultVersionSpec : version, out var semver)) { Console.Error.WriteLine($"\"{version}\" is not a semver-compliant version spec."); return(ExitCodes.InvalidVersionSpec); } var options = new VersionOptions { Version = semver, PublicReleaseRefSpec = new string[] { @"^refs/heads/master$", @"^refs/heads/v\d+(?:\.\d+)?$", }, CloudBuild = new VersionOptions.CloudBuildOptions { BuildNumber = new VersionOptions.CloudBuildNumberOptions { Enabled = true, }, }, }; string searchPath = GetSpecifiedOrCurrentDirectoryPath(versionJsonRoot); if (!Directory.Exists(searchPath)) { Console.Error.WriteLine("\"{0}\" is not an existing directory.", searchPath); return(ExitCodes.NoGitRepo); } var repository = GitExtensions.OpenGitRepo(searchPath); if (repository == null) { Console.Error.WriteLine("No git repo found at or above: \"{0}\"", searchPath); return(ExitCodes.NoGitRepo); } if (string.IsNullOrEmpty(versionJsonRoot)) { versionJsonRoot = repository.Info.WorkingDirectory; } var existingOptions = VersionFile.GetVersion(versionJsonRoot); if (existingOptions != null) { if (!string.IsNullOrEmpty(version)) { var setVersionExitCode = OnSetVersionCommand(versionJsonRoot, version); if (setVersionExitCode != ExitCodes.OK) { return(setVersionExitCode); } } } else { string versionJsonPath = VersionFile.SetVersion(versionJsonRoot, options); LibGit2Sharp.Commands.Stage(repository, versionJsonPath); } // Create/update the Directory.Build.props file in the directory of the version.json file to add the NB.GV package. string directoryBuildPropsPath = Path.Combine(versionJsonRoot, "Directory.Build.props"); MSBuild.Project propsFile; if (File.Exists(directoryBuildPropsPath)) { propsFile = new MSBuild.Project(directoryBuildPropsPath); } else { propsFile = new MSBuild.Project(); } const string PackageReferenceItemType = "PackageReference"; if (!propsFile.GetItemsByEvaluatedInclude(PackageId).Any(i => i.ItemType == "PackageReference")) { // Validate given sources foreach (var source in sources) { if (!Uri.TryCreate(source, UriKind.Absolute, out var _)) { Console.Error.WriteLine($"\"{source}\" is not a valid NuGet package source."); return(ExitCodes.InvalidNuGetPackageSource); } } string packageVersion = GetLatestPackageVersionAsync(PackageId, versionJsonRoot, sources).GetAwaiter().GetResult(); if (string.IsNullOrEmpty(packageVersion)) { string verifyPhrase = sources.Any() ? "Please verify the given 'source' option(s)." : "Please verify the package sources in the NuGet.Config files."; Console.Error.WriteLine($"Latest stable version of the {PackageId} package could not be determined. " + verifyPhrase); return(ExitCodes.PackageIdNotFound); } propsFile.AddItem( PackageReferenceItemType, PackageId, new Dictionary <string, string> { { "Version", packageVersion }, { "PrivateAssets", "all" }, }); propsFile.Save(directoryBuildPropsPath); } LibGit2Sharp.Commands.Stage(repository, directoryBuildPropsPath); return(ExitCodes.OK); }
public override bool Execute() { try { Version typedVersion; VersionOptions versionOptions; using (var git = this.OpenGitRepo()) { var repoRoot = git?.Info?.WorkingDirectory?.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); var relativeRepoProjectDirectory = !string.IsNullOrWhiteSpace(repoRoot) ? Environment.CurrentDirectory.Substring(repoRoot.Length).TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) : null; var commit = git?.Head.Commits.FirstOrDefault(); this.GitCommitId = commit?.Id.Sha ?? string.Empty; this.GitVersionHeight = git?.GetVersionHeight(relativeRepoProjectDirectory) ?? 0; if (string.IsNullOrEmpty(this.BuildingRef)) { this.BuildingRef = git?.Head.CanonicalName; } versionOptions = VersionFile.GetVersion(git, Environment.CurrentDirectory) ?? VersionFile.GetVersion(Environment.CurrentDirectory); this.PublicRelease = string.Equals(this.DefaultPublicRelease, "true", StringComparison.OrdinalIgnoreCase); if (string.IsNullOrEmpty(this.DefaultPublicRelease)) { if (!string.IsNullOrEmpty(this.BuildingRef) && versionOptions?.PublicReleaseRefSpec?.Length > 0) { this.PublicRelease = versionOptions.PublicReleaseRefSpec.Any( expr => Regex.IsMatch(this.BuildingRef, expr)); } } this.PrereleaseVersion = versionOptions?.Version.Prerelease ?? string.Empty; // Override the typedVersion with the special build number and revision components, when available. typedVersion = git?.GetIdAsVersion(relativeRepoProjectDirectory, this.GitVersionHeight) ?? versionOptions?.Version.Version; } typedVersion = typedVersion ?? new Version(); var typedVersionWithoutRevision = typedVersion.Build >= 0 ? new Version(typedVersion.Major, typedVersion.Minor, typedVersion.Build) : new Version(typedVersion.Major, typedVersion.Minor); this.SimpleVersion = typedVersionWithoutRevision.ToString(); var majorMinorVersion = new Version(typedVersion.Major, typedVersion.Minor); this.MajorMinorVersion = majorMinorVersion.ToString(); Version assemblyVersion = GetAssemblyVersion(typedVersion, versionOptions); this.AssemblyVersion = assemblyVersion.ToStringSafe(4); this.BuildNumber = Math.Max(0, typedVersion.Build); this.Version = typedVersion.ToString(); this.SetCloudBuildVersionVars = versionOptions?.CloudBuild?.SetVersionVariables ?? (new VersionOptions.CloudBuildOptions()).SetVersionVariables; var buildMetadata = this.BuildMetadata?.ToList() ?? new List <string>(); if (!string.IsNullOrEmpty(this.GitCommitId)) { buildMetadata.Insert(0, $"g{this.GitCommitId.Substring(0, 10)}"); } this.BuildMetadataFragment = FormatBuildMetadata(buildMetadata); var buildNumber = versionOptions?.CloudBuild?.BuildNumber ?? new VersionOptions.CloudBuildNumberOptions(); if (buildNumber.Enabled) { var commitIdOptions = buildNumber.IncludeCommitId ?? new VersionOptions.CloudBuildNumberCommitIdOptions(); bool includeCommitInfo = commitIdOptions.When == VersionOptions.CloudBuildNumberCommitWhen.Always || (commitIdOptions.When == VersionOptions.CloudBuildNumberCommitWhen.NonPublicReleaseOnly && !this.PublicRelease); bool commitIdInRevision = includeCommitInfo && commitIdOptions.Where == VersionOptions.CloudBuildNumberCommitWhere.FourthVersionComponent; bool commitIdInBuildMetadata = includeCommitInfo && commitIdOptions.Where == VersionOptions.CloudBuildNumberCommitWhere.BuildMetadata; Version buildNumberVersion = commitIdInRevision ? typedVersion : typedVersionWithoutRevision; string buildNumberMetadata = FormatBuildMetadata(commitIdInBuildMetadata ? (IEnumerable <string>)buildMetadata : this.BuildMetadata); this.CloudBuildNumber = buildNumberVersion + this.PrereleaseVersion + buildNumberMetadata; } } catch (ArgumentOutOfRangeException ex) { Log.LogErrorFromException(ex); return(false); } return(true); }
public void VersionJson_Inheritance(bool commitInSourceControl, bool bareRepo) { if (commitInSourceControl) { this.InitializeSourceControl(); } VersionOptions level1, level2, level3, level2NoInherit, level2InheritButResetVersion; this.WriteVersionFile( level1 = new VersionOptions { Version = SemanticVersion.Parse("14.2"), AssemblyVersion = new VersionOptions.AssemblyVersionOptions { Precision = VersionOptions.VersionPrecision.Major }, }); this.WriteVersionFile( level2 = new VersionOptions { Inherit = true, AssemblyVersion = new VersionOptions.AssemblyVersionOptions { Precision = VersionOptions.VersionPrecision.Minor }, }, "foo"); this.WriteVersionFile( level3 = new VersionOptions { Inherit = true, VersionHeightOffset = 1, }, @"foo\bar"); this.WriteVersionFile( level2NoInherit = new VersionOptions { Version = SemanticVersion.Parse("10.1"), }, @"noInherit"); this.WriteVersionFile( level2InheritButResetVersion = new VersionOptions { Inherit = true, Version = SemanticVersion.Parse("8.2"), }, @"inheritWithVersion"); Repository operatingRepo = this.Repo; if (bareRepo) { operatingRepo = new Repository( Repository.Clone(this.RepoPath, this.CreateDirectoryForNewRepo(), new CloneOptions { IsBare = true })); } using (operatingRepo) { VersionOptions GetOption(string path) => commitInSourceControl?VersionFile.GetVersion(operatingRepo, path) : VersionFile.GetVersion(Path.Combine(this.RepoPath, path)); var level1Options = GetOption(string.Empty); Assert.False(level1Options.Inherit); var level2Options = GetOption("foo"); Assert.Equal(level1.Version.Version.Major, level2Options.Version.Version.Major); Assert.Equal(level1.Version.Version.Minor, level2Options.Version.Version.Minor); Assert.Equal(level2.AssemblyVersion.Precision, level2Options.AssemblyVersion.Precision); Assert.True(level2Options.Inherit); var level3Options = GetOption(@"foo\bar"); Assert.Equal(level1.Version.Version.Major, level3Options.Version.Version.Major); Assert.Equal(level1.Version.Version.Minor, level3Options.Version.Version.Minor); Assert.Equal(level2.AssemblyVersion.Precision, level3Options.AssemblyVersion.Precision); Assert.Equal(level2.AssemblyVersion.Precision, level3Options.AssemblyVersion.Precision); Assert.Equal(level3.VersionHeightOffset, level3Options.VersionHeightOffset); Assert.True(level3Options.Inherit); var level2NoInheritOptions = GetOption("noInherit"); Assert.Equal(level2NoInherit.Version, level2NoInheritOptions.Version); Assert.Equal(VersionOptions.DefaultVersionPrecision, level2NoInheritOptions.AssemblyVersionOrDefault.PrecisionOrDefault); Assert.False(level2NoInheritOptions.Inherit); var level2InheritButResetVersionOptions = GetOption("inheritWithVersion"); Assert.Equal(level2InheritButResetVersion.Version, level2InheritButResetVersionOptions.Version); Assert.True(level2InheritButResetVersionOptions.Inherit); if (commitInSourceControl) { int totalCommits = operatingRepo.Head.Commits.Count(); // The version height should be the same for all those that inherit the version from the base, // even though the inheriting files were introduced in successive commits. Assert.Equal(totalCommits, operatingRepo.GetVersionHeight()); Assert.Equal(totalCommits, operatingRepo.GetVersionHeight("foo")); Assert.Equal(totalCommits, operatingRepo.GetVersionHeight(@"foo\bar")); // These either don't inherit, or inherit but reset versions, so the commits were reset. Assert.Equal(2, operatingRepo.GetVersionHeight("noInherit")); Assert.Equal(1, operatingRepo.GetVersionHeight("inheritWithVersion")); } } }
private static ExitCodes OnInstallCommand(string versionJsonRoot, string version) { if (!SemanticVersion.TryParse(string.IsNullOrEmpty(version) ? DefaultVersionSpec : version, out var semver)) { Console.Error.WriteLine($"\"{version}\" is not a semver-compliant version spec."); return(ExitCodes.InvalidVersionSpec); } var options = new VersionOptions { Version = semver, PublicReleaseRefSpec = new string[] { @"^refs/heads/master$", @"^refs/heads/v\d+(?:\.\d+)?$", }, CloudBuild = new VersionOptions.CloudBuildOptions { BuildNumber = new VersionOptions.CloudBuildNumberOptions { Enabled = true, }, }, }; string searchPath = GetSpecifiedOrCurrentDirectoryPath(versionJsonRoot); if (!Directory.Exists(searchPath)) { Console.Error.WriteLine("\"{0}\" is not an existing directory.", searchPath); return(ExitCodes.NoGitRepo); } var repository = GitExtensions.OpenGitRepo(searchPath); if (repository == null) { Console.Error.WriteLine("No git repo found at or above: \"{0}\"", searchPath); return(ExitCodes.NoGitRepo); } if (string.IsNullOrEmpty(versionJsonRoot)) { versionJsonRoot = repository.Info.WorkingDirectory; } var existingOptions = VersionFile.GetVersion(versionJsonRoot); if (existingOptions != null) { if (!string.IsNullOrEmpty(version)) { var setVersionExitCode = OnSetVersionCommand(versionJsonRoot, version); if (setVersionExitCode != ExitCodes.OK) { return(setVersionExitCode); } } } else { string versionJsonPath = VersionFile.SetVersion(versionJsonRoot, options); LibGit2Sharp.Commands.Stage(repository, versionJsonPath); } // Create/update the Directory.Build.props file in the directory of the version.json file to add the NB.GV package. string directoryBuildPropsPath = Path.Combine(versionJsonRoot, "Directory.Build.props"); MSBuild.Project propsFile; if (File.Exists(directoryBuildPropsPath)) { propsFile = new MSBuild.Project(directoryBuildPropsPath); } else { propsFile = new MSBuild.Project(); } const string PackageReferenceItemType = "PackageReference"; const string PackageId = "Nerdbank.GitVersioning"; if (!propsFile.GetItemsByEvaluatedInclude(PackageId).Any(i => i.ItemType == "PackageReference")) { string packageVersion = GetLatestPackageVersionAsync(PackageId).GetAwaiter().GetResult(); propsFile.AddItem( PackageReferenceItemType, PackageId, new Dictionary <string, string> { { "Version", packageVersion }, // TODO: use the latest version... somehow... { "PrivateAssets", "all" }, }); propsFile.Save(directoryBuildPropsPath); } LibGit2Sharp.Commands.Stage(repository, directoryBuildPropsPath); return(ExitCodes.OK); }
public void GetVersion_String_MissingFile() { Assert.Null(VersionFile.GetVersion(this.RepoPath)); }