public void GetVersionManaged() { using var context = GitContext.Create(GetPath(this.ProjectDirectory), writable: false); var oracle = new VersionOracle(context, cloudBuild: null); this.Version = oracle.Version; }
protected Commit?WriteVersionFile(VersionOptions versionData, string?relativeDirectory = null) { Requires.NotNull(versionData, nameof(versionData)); if (relativeDirectory == null) { relativeDirectory = string.Empty; } bool localContextCreated = this.Context is null; var context = this.Context ?? GitContext.Create(this.RepoPath, writable: true); try { string versionFilePath = context.VersionFile.SetVersion(Path.Combine(this.RepoPath, relativeDirectory), versionData); return(this.CommitVersionFile(versionFilePath, versionData.Version?.ToString())); } finally { if (localContextCreated) { context.Dispose(); } } }
public static VersionOracle GitVersioningGetVersion(this ICakeContext cakeContext, string projectDirectory = ".") { var fullProjectDirectory = (new DirectoryInfo(projectDirectory)).FullName; string directoryName = Path.GetDirectoryName(Assembly.GetAssembly(typeof(GitVersioningAliases)).Location); if (string.IsNullOrWhiteSpace(directoryName)) { throw new InvalidOperationException("Could not locate the Cake.GitVersioning library"); } var gitContext = GitContext.Create(fullProjectDirectory); return(new VersionOracle(gitContext, cloudBuild: CloudBuild.Active)); }
private static int OnSetVersionCommand(string project, 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((int)ExitCodes.InvalidVersionSpec); } var defaultOptions = new VersionOptions { Version = semver, }; string searchPath = GetSpecifiedOrCurrentDirectoryPath(project); using var context = GitContext.Create(searchPath, writable: true); var existingOptions = context.VersionFile.GetVersion(out string actualDirectory); string versionJsonPath; if (existingOptions != null) { existingOptions.Version = semver; versionJsonPath = context.VersionFile.SetVersion(actualDirectory, existingOptions); } else if (string.IsNullOrEmpty(project)) { if (!context.IsRepository) { Console.Error.WriteLine("No version file and no git repo found at or above: \"{0}\"", searchPath); return((int)ExitCodes.NoGitRepo); } versionJsonPath = context.VersionFile.SetVersion(context.WorkingTreePath, defaultOptions); } else { versionJsonPath = context.VersionFile.SetVersion(project, defaultOptions); } if (context.IsRepository) { context.Stage(versionJsonPath); } return((int)ExitCodes.OK); }
private static int OnGetCommitsCommand(string project, bool quiet, string version) { if (!Version.TryParse(version, out Version parsedVersion)) { Console.Error.WriteLine($"\"{version}\" is not a simple a.b.c[.d] version spec."); return((int)ExitCodes.InvalidVersionSpec); } string searchPath = GetSpecifiedOrCurrentDirectoryPath(project); using var context = (LibGit2Context)GitContext.Create(searchPath, writable: true); if (!context.IsRepository) { Console.Error.WriteLine("No git repo found at or above: \"{0}\"", searchPath); return((int)ExitCodes.NoGitRepo); } var candidateCommits = LibGit2GitExtensions.GetCommitsFromVersion(context, parsedVersion); PrintCommits(quiet, context, candidateCommits); return((int)ExitCodes.OK); }
protected override GitContext CreateGitContext(string path, string committish = null) => GitContext.Create(path, committish, writable: true);
/// <summary> /// Adds version variables to the the current cloud build environment. /// </summary> /// <exception cref="CloudCommandException">Thrown when the build environment could not be updated.</exception> /// <param name="projectDirectory"> /// The path to the directory which may (or its ancestors may) define the version file. /// </param> /// <param name="metadata"> /// Optionally adds an identifier to the build metadata part of a semantic version. /// </param> /// <param name="version"> /// The string to use for the cloud build number. If not specified, the computed version will be used. /// </param> /// <param name="ciSystem"> /// The CI system to activate. If not specified, auto-detection will be used. /// </param> /// <param name="allVars"> /// Controls whether to define all version variables as cloud build variables. /// </param> /// <param name="commonVars"> /// Controls whether to define common version variables as cloud build variables. /// </param> /// <param name="additionalVariables"> /// Additional cloud build variables to define. /// </param> /// <param name="alwaysUseLibGit2"> /// Force usage of LibGit2 for accessing the git repository. /// </param> public void SetBuildVariables(string projectDirectory, IEnumerable <string> metadata, string version, string ciSystem, bool allVars, bool commonVars, IEnumerable <KeyValuePair <string, string> > additionalVariables, bool alwaysUseLibGit2) { Requires.NotNull(projectDirectory, nameof(projectDirectory)); Requires.NotNull(additionalVariables, nameof(additionalVariables)); ICloudBuild activeCloudBuild = CloudBuild.Active; if (!string.IsNullOrEmpty(ciSystem)) { int matchingIndex = Array.FindIndex(CloudProviderNames, m => string.Equals(m, ciSystem, StringComparison.OrdinalIgnoreCase)); if (matchingIndex == -1) { throw new CloudCommandException( $"No cloud provider found by the name: \"{ciSystem}\"", CloudCommandError.NoCloudBuildProviderMatch); } activeCloudBuild = CloudBuild.SupportedCloudBuilds[matchingIndex]; } using var context = GitContext.Create(projectDirectory, writable: alwaysUseLibGit2); var oracle = new VersionOracle(context, cloudBuild: activeCloudBuild); if (metadata is not null) { oracle.BuildMetadata.AddRange(metadata); } var variables = new Dictionary <string, string>(); if (allVars) { foreach (var pair in oracle.CloudBuildAllVars) { variables.Add(pair.Key, pair.Value); } } if (commonVars) { foreach (var pair in oracle.CloudBuildVersionVars) { variables.Add(pair.Key, pair.Value); } } foreach (var kvp in additionalVariables) { if (variables.ContainsKey(kvp.Key)) { throw new CloudCommandException( $"Cloud build variable \"{kvp.Key}\" specified more than once.", CloudCommandError.DuplicateCloudVariable); } variables[kvp.Key] = kvp.Value; } if (activeCloudBuild is not null) { if (string.IsNullOrEmpty(version)) { version = oracle.CloudBuildNumber; } activeCloudBuild.SetCloudBuildNumber(version, this.stdout, this.stderr); foreach (var pair in variables) { activeCloudBuild.SetCloudBuildVariable(pair.Key, pair.Value, this.stdout, this.stderr); } } else { throw new CloudCommandException( "No cloud build detected.", CloudCommandError.NoCloudBuildEnvDetected); } }
private static int OnCloudCommand(string project, IReadOnlyList <string> metadata, string version, string ciSystem, bool allVars, bool commonVars, IReadOnlyList <string> define) { string searchPath = GetSpecifiedOrCurrentDirectoryPath(project); if (!Directory.Exists(searchPath)) { Console.Error.WriteLine("\"{0}\" is not an existing directory.", searchPath); return((int)ExitCodes.NoGitRepo); } ICloudBuild activeCloudBuild = CloudBuild.Active; if (!string.IsNullOrEmpty(ciSystem)) { int matchingIndex = Array.FindIndex(CloudProviderNames, m => string.Equals(m, ciSystem, StringComparison.OrdinalIgnoreCase)); if (matchingIndex == -1) { Console.Error.WriteLine("No cloud provider found by the name: \"{0}\"", ciSystem); return((int)ExitCodes.NoCloudBuildProviderMatch); } activeCloudBuild = CloudBuild.SupportedCloudBuilds[matchingIndex]; } using var context = GitContext.Create(searchPath, writable: AlwaysUseLibGit2); var oracle = new VersionOracle(context, cloudBuild: activeCloudBuild); if (metadata != null) { oracle.BuildMetadata.AddRange(metadata); } var variables = new Dictionary <string, string>(); if (allVars) { foreach (var pair in oracle.CloudBuildAllVars) { variables.Add(pair.Key, pair.Value); } } if (commonVars) { foreach (var pair in oracle.CloudBuildVersionVars) { variables.Add(pair.Key, pair.Value); } } if (define != null) { foreach (string def in define) { string[] split = def.Split(new char[] { '=' }, 2); if (split.Length < 2) { Console.Error.WriteLine($"\"{def}\" is not in the NAME=VALUE syntax required for cloud variables."); return((int)ExitCodes.BadCloudVariable); } if (variables.ContainsKey(split[0])) { Console.Error.WriteLine($"Cloud build variable \"{split[0]}\" specified more than once."); return((int)ExitCodes.DuplicateCloudVariable); } variables[split[0]] = split[1]; } } if (activeCloudBuild != null) { if (string.IsNullOrEmpty(version)) { version = oracle.CloudBuildNumber; } activeCloudBuild.SetCloudBuildNumber(version, Console.Out, Console.Error); foreach (var pair in variables) { activeCloudBuild.SetCloudBuildVariable(pair.Key, pair.Value, Console.Out, Console.Error); } return((int)ExitCodes.OK); } else { Console.Error.WriteLine("No cloud build detected."); return((int)ExitCodes.NoCloudBuildEnvDetected); } }
private static int OnTagCommand(string project, string versionOrRef) { if (string.IsNullOrEmpty(versionOrRef)) { versionOrRef = DefaultRef; } string searchPath = GetSpecifiedOrCurrentDirectoryPath(project); using var context = (LibGit2Context)GitContext.Create(searchPath, writable: true); if (context is null) { Console.Error.WriteLine("No git repo found at or above: \"{0}\"", searchPath); return((int)ExitCodes.NoGitRepo); } var repository = context.Repository; if (!context.TrySelectCommit(versionOrRef)) { if (!Version.TryParse(versionOrRef, out Version parsedVersion)) { Console.Error.WriteLine($"\"{versionOrRef}\" is not a simple a.b.c[.d] version spec or git reference."); return((int)ExitCodes.InvalidVersionSpec); } string repoRelativeProjectDir = GetRepoRelativePath(searchPath, repository); var candidateCommits = LibGit2GitExtensions.GetCommitsFromVersion(context, parsedVersion).ToList(); if (candidateCommits.Count == 0) { Console.Error.WriteLine("No commit with that version found."); return((int)ExitCodes.NoMatchingVersion); } else if (candidateCommits.Count > 1) { PrintCommits(false, context, candidateCommits, includeOptions: true); int selection; do { Console.Write("Enter selection: "); }while (!int.TryParse(Console.ReadLine(), out selection) || selection > candidateCommits.Count || selection < 1); context.TrySelectCommit(candidateCommits[selection - 1].Sha); } else { context.TrySelectCommit(candidateCommits.Single().Sha); } } var oracle = new VersionOracle(context, CloudBuild.Active); if (!oracle.VersionFileFound) { Console.Error.WriteLine("No version.json file found in or above \"{0}\" in commit {1}.", searchPath, context.GitCommitId); return((int)ExitCodes.NoVersionJsonFound); } oracle.PublicRelease = true; // assume a public release so we don't get a redundant -gCOMMITID in the tag name string tagName = $"v{oracle.SemVer2}"; try { context.ApplyTag(tagName); } catch (LibGit2Sharp.NameConflictException) { var taggedCommit = repository.Tags[tagName].Target as LibGit2Sharp.Commit; bool correctTag = taggedCommit?.Sha == context.GitCommitId; Console.Error.WriteLine("The tag {0} is already defined ({1}).", tagName, correctTag ? "to the right commit" : $"expected {context.GitCommitId} but was on {taggedCommit.Sha}"); return((int)(correctTag ? ExitCodes.OK : ExitCodes.TagConflict)); } Console.WriteLine("{0} tag created at {1}.", tagName, context.GitCommitId); Console.WriteLine("Remember to push to a remote: git push origin {0}", tagName); return((int)ExitCodes.OK); }
private static int OnGetVersionCommand(string project, IReadOnlyList <string> metadata, string format, string variable, string commitIsh) { if (string.IsNullOrEmpty(format)) { format = DefaultOutputFormat; } if (string.IsNullOrEmpty(commitIsh)) { commitIsh = DefaultRef; } string searchPath = GetSpecifiedOrCurrentDirectoryPath(project); using var context = GitContext.Create(searchPath, writable: AlwaysUseLibGit2); if (!context.IsRepository) { Console.Error.WriteLine("No git repo found at or above: \"{0}\"", searchPath); return((int)ExitCodes.NoGitRepo); } if (!context.TrySelectCommit(commitIsh)) { Console.Error.WriteLine("rev-parse produced no commit for {0}", commitIsh); return((int)ExitCodes.BadGitRef); } var oracle = new VersionOracle(context, CloudBuild.Active); if (metadata != null) { oracle.BuildMetadata.AddRange(metadata); } // Take the PublicRelease environment variable into account, since the build would as well. if (!string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("PublicRelease")) && bool.TryParse(Environment.GetEnvironmentVariable("PublicRelease"), out bool publicRelease)) { oracle.PublicRelease = publicRelease; } if (string.IsNullOrEmpty(variable)) { switch (format.ToLowerInvariant()) { case "text": Console.WriteLine("Version: {0}", oracle.Version); Console.WriteLine("AssemblyVersion: {0}", oracle.AssemblyVersion); Console.WriteLine("AssemblyInformationalVersion: {0}", oracle.AssemblyInformationalVersion); Console.WriteLine("NuGetPackageVersion: {0}", oracle.NuGetPackageVersion); Console.WriteLine("NpmPackageVersion: {0}", oracle.NpmPackageVersion); break; case "json": var converters = new JsonConverter[] { new Newtonsoft.Json.Converters.VersionConverter(), }; Console.WriteLine(JsonConvert.SerializeObject(oracle, Formatting.Indented, converters)); break; default: Console.Error.WriteLine("Unsupported format: {0}", format); return((int)ExitCodes.UnsupportedFormat); } } else { if (format != "text") { Console.Error.WriteLine("Format must be \"text\" when querying for an individual variable's value."); return((int)ExitCodes.UnsupportedFormat); } var property = oracle.GetType().GetProperty(variable, CaseInsensitiveFlags); if (property == null) { Console.Error.WriteLine("Variable \"{0}\" not a version property.", variable); return((int)ExitCodes.BadVariable); } Console.WriteLine(property.GetValue(oracle)); } return((int)ExitCodes.OK); }
private static int OnInstallCommand(string path, string version, IReadOnlyList <string> source) { if (!SemanticVersion.TryParse(string.IsNullOrEmpty(version) ? DefaultVersionSpec : version, out var semver)) { Console.Error.WriteLine($"\"{version}\" is not a semver-compliant version spec."); return((int)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(path); if (!Directory.Exists(searchPath)) { Console.Error.WriteLine("\"{0}\" is not an existing directory.", searchPath); return((int)ExitCodes.NoGitRepo); } using var context = GitContext.Create(searchPath, writable: true); if (!context.IsRepository) { Console.Error.WriteLine("No git repo found at or above: \"{0}\"", searchPath); return((int)ExitCodes.NoGitRepo); } if (string.IsNullOrEmpty(path)) { path = context.WorkingTreePath; } var existingOptions = context.VersionFile.GetVersion(); if (existingOptions != null) { if (!string.IsNullOrEmpty(version)) { var setVersionExitCode = OnSetVersionCommand(path, version); if (setVersionExitCode != (int)ExitCodes.OK) { return(setVersionExitCode); } } } else { string versionJsonPath = context.VersionFile.SetVersion(path, options); context.Stage(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(path, "Directory.Build.props"); ProjectRootElement propsFile = File.Exists(directoryBuildPropsPath) ? ProjectRootElement.Open(directoryBuildPropsPath) : ProjectRootElement.Create(directoryBuildPropsPath); const string PackageReferenceItemType = "PackageReference"; if (!propsFile.Items.Any(i => i.ItemType == PackageReferenceItemType && i.Include == PackageId)) { // Validate given sources foreach (var src in source) { // TODO: Can declare Option<Uri> to validate argument during parsing. if (!Uri.TryCreate(src, UriKind.Absolute, out var _)) { Console.Error.WriteLine($"\"{src}\" is not a valid NuGet package source."); return((int)ExitCodes.InvalidNuGetPackageSource); } } string packageVersion = GetLatestPackageVersionAsync(PackageId, path, source).GetAwaiter().GetResult(); if (string.IsNullOrEmpty(packageVersion)) { string verifyPhrase = source.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((int)ExitCodes.PackageIdNotFound); } var item = propsFile.AddItem( PackageReferenceItemType, PackageId, new Dictionary <string, string> { { "Version", packageVersion }, { "PrivateAssets", "all" }, }); item.Condition = "!Exists('packages.config')"; propsFile.Save(directoryBuildPropsPath); } context.Stage(directoryBuildPropsPath); return((int)ExitCodes.OK); }
protected override bool ExecuteInner() { try { if (!string.IsNullOrEmpty(this.ProjectPathRelativeToGitRepoRoot)) { Requires.Argument(!Path.IsPathRooted(this.ProjectPathRelativeToGitRepoRoot), nameof(this.ProjectPathRelativeToGitRepoRoot), "Path must be relative."); Requires.Argument(!( this.ProjectPathRelativeToGitRepoRoot.Contains(".." + Path.DirectorySeparatorChar) || this.ProjectPathRelativeToGitRepoRoot.Contains(".." + Path.AltDirectorySeparatorChar)), nameof(this.ProjectPathRelativeToGitRepoRoot), "Path must not use ..\\"); } bool useLibGit2 = false; if (!string.IsNullOrWhiteSpace(this.GitEngine)) { useLibGit2 = this.GitEngine == "Managed" ? false : this.GitEngine == "LibGit2" ? true : throw new ArgumentException("GitEngine property must be set to either \"Managed\" or \"LibGit2\" or left empty."); } var cloudBuild = CloudBuild.Active; var overrideBuildNumberOffset = (this.OverrideBuildNumberOffset == int.MaxValue) ? (int?)null : this.OverrideBuildNumberOffset; string projectDirectory = this.ProjectPathRelativeToGitRepoRoot is object && this.GitRepoRoot is object ?Path.Combine(this.GitRepoRoot, this.ProjectPathRelativeToGitRepoRoot) : this.ProjectDirectory; using var context = GitContext.Create(projectDirectory, writable: useLibGit2); var oracle = new VersionOracle(context, cloudBuild, overrideBuildNumberOffset); if (!string.IsNullOrEmpty(this.DefaultPublicRelease)) { oracle.PublicRelease = string.Equals(this.DefaultPublicRelease, "true", StringComparison.OrdinalIgnoreCase); } if (this.BuildMetadata != null) { oracle.BuildMetadata.AddRange(this.BuildMetadata.Split(';')); } if (IsMisconfiguredPrereleaseAndSemVer1(oracle)) { this.Log.LogWarning("The 'nugetPackageVersion' is explicitly set to 'semVer': 1 but the prerelease version '{0}' is not SemVer1 compliant. Change the 'nugetPackageVersion'.'semVer' value to 2 or change the 'version' member to follow SemVer1 rules (e.g.: '{1}').", oracle.PrereleaseVersion, GetSemVer1WithoutPaddingOrBuildMetadata(oracle)); } this.PublicRelease = oracle.PublicRelease; this.BuildingRef = oracle.BuildingRef; this.Version = oracle.Version.ToString(); this.AssemblyVersion = oracle.AssemblyVersion.ToString(); this.AssemblyFileVersion = oracle.AssemblyFileVersion.ToString(); this.AssemblyInformationalVersion = oracle.AssemblyInformationalVersion; this.SimpleVersion = oracle.SimpleVersion.ToString(); this.MajorMinorVersion = oracle.MajorMinorVersion.ToString(); this.BuildNumber = oracle.BuildNumber; this.PrereleaseVersion = oracle.PrereleaseVersion; this.GitCommitId = oracle.GitCommitId; this.GitCommitIdShort = oracle.GitCommitIdShort; this.GitCommitDateTicks = oracle.GitCommitDate != null?oracle.GitCommitDate.Value.UtcTicks.ToString(CultureInfo.InvariantCulture) : null; this.GitVersionHeight = oracle.VersionHeight; this.BuildMetadataFragment = oracle.BuildMetadataFragment; this.CloudBuildNumber = oracle.CloudBuildNumberEnabled ? oracle.CloudBuildNumber : null; this.NuGetPackageVersion = oracle.NuGetPackageVersion; this.ChocolateyPackageVersion = oracle.ChocolateyPackageVersion; this.NpmPackageVersion = oracle.NpmPackageVersion; IEnumerable <ITaskItem> cloudBuildVersionVars = null; if (oracle.CloudBuildVersionVarsEnabled) { cloudBuildVersionVars = oracle.CloudBuildVersionVars .Select(item => new TaskItem(item.Key, new Dictionary <string, string> { { "Value", item.Value } })); } if (oracle.CloudBuildAllVarsEnabled) { var allVariables = oracle.CloudBuildAllVars .Select(item => new TaskItem(item.Key, new Dictionary <string, string> { { "Value", item.Value } })); if (cloudBuildVersionVars != null) { cloudBuildVersionVars = cloudBuildVersionVars .Union(allVariables); } else { cloudBuildVersionVars = allVariables; } } if (cloudBuildVersionVars != null) { this.CloudBuildVersionVars = cloudBuildVersionVars.ToArray(); } var outputProperties = new Dictionary <string, PropertySet>(StringComparer.OrdinalIgnoreCase) { { "BuildVersion", this.Version }, { "AssemblyInformationalVersion", this.AssemblyInformationalVersion }, { "AssemblyFileVersion", this.AssemblyFileVersion }, { "FileVersion", this.AssemblyFileVersion }, { "BuildVersionSimple", this.SimpleVersion }, { "PrereleaseVersion", this.PrereleaseVersion }, { "MajorMinorVersion", this.MajorMinorVersion }, { "AssemblyVersion", this.AssemblyVersion }, { "GitCommitId", this.GitCommitId }, { "GitCommitIdShort", this.GitCommitIdShort }, { "GitCommitDateTicks", this.GitCommitDateTicks }, { "GitVersionHeight", this.GitVersionHeight.ToString(CultureInfo.InvariantCulture) }, { "BuildNumber", this.BuildNumber.ToString(CultureInfo.InvariantCulture) }, { "BuildVersionNumberComponent", this.BuildNumber.ToString(CultureInfo.InvariantCulture) }, { "PublicRelease", this.PublicRelease.ToString(CultureInfo.InvariantCulture) }, { "BuildingRef", this.BuildingRef }, { "CloudBuildNumber", new PropertySet(this.CloudBuildNumber) { HonorPresetValue = true } }, { "SemVerBuildSuffix", this.BuildMetadataFragment }, { "NuGetPackageVersion", this.NuGetPackageVersion }, { "ChocolateyPackageVersion", this.ChocolateyPackageVersion }, { "Version", this.NuGetPackageVersion }, { "PackageVersion", this.NuGetPackageVersion }, { "NPMPackageVersion", this.NpmPackageVersion.ToString(CultureInfo.InvariantCulture) }, { "BuildVersion3Components", $"{this.MajorMinorVersion}.{this.BuildNumber}" }, }; this.OutputProperties = outputProperties.Select(kv => { var item = new TaskItem(kv.Key); item.SetMetadata("Value", kv.Value.Value); item.SetMetadata("HonorPresetValue", kv.Value.HonorPresetValue ? "true" : "false"); return(item); }).ToArray(); return(!this.Log.HasLoggedErrors); } catch (ArgumentOutOfRangeException ex) { this.Log.LogErrorFromException(ex); return(false); } }