/// <summary> /// Initializes a new instance of the <see cref="VersionOracle"/> class. /// </summary> public static VersionOracle Create(string projectDirectory, string gitRepoDirectory = null, ICloudBuild cloudBuild = null, int?overrideBuildNumberOffset = null, string projectPathRelativeToGitRepoRoot = null) { Requires.NotNull(projectDirectory, nameof(projectDirectory)); if (string.IsNullOrEmpty(gitRepoDirectory)) { gitRepoDirectory = projectDirectory; } using (var git = GitExtensions.OpenGitRepo(gitRepoDirectory)) { return(new VersionOracle(projectDirectory, git, null, cloudBuild, overrideBuildNumberOffset, projectPathRelativeToGitRepoRoot)); } }
/// <summary> /// Writes the version.json file to a directory within a repo with the specified version information. /// </summary> /// <param name="projectDirectory"> /// The path to the directory in which to write the version.json file. /// The file's impact will be all descendent projects and directories from this specified directory, /// except where any of those directories have their own version.json file. /// </param> /// <param name="version">The version information to write to the file.</param> /// <param name="includeSchemaProperty">A value indicating whether to serialize the $schema property for easier editing in most JSON editors.</param> /// <returns>The path to the file written.</returns> public static string SetVersion(string projectDirectory, VersionOptions version, bool includeSchemaProperty) { Requires.NotNullOrEmpty(projectDirectory, nameof(projectDirectory)); Requires.NotNull(version, nameof(version)); Requires.Argument(version.Version != null || version.Inherit, nameof(version), $"{nameof(VersionOptions.Version)} must be set for a root-level version.json file."); Directory.CreateDirectory(projectDirectory); string versionTxtPath = Path.Combine(projectDirectory, TxtFileName); if (File.Exists(versionTxtPath)) { if (version.IsDefaultVersionTheOnlyPropertySet) { File.WriteAllLines( versionTxtPath, new[] { version.Version.Version.ToString(), version.Version.Prerelease }); return(versionTxtPath); } else { // The file must be upgraded to use the more descriptive JSON format. File.Delete(versionTxtPath); } } using (var repo = GitExtensions.OpenGitRepo(projectDirectory)) { string repoRelativeProjectDirectory = repo?.GetRepoRelativePath(projectDirectory); string versionJsonPath = Path.Combine(projectDirectory, JsonFileName); var jsonContent = JsonConvert.SerializeObject(version, VersionOptions.GetJsonSettings(version.Inherit, includeSchemaProperty, repoRelativeProjectDirectory)); File.WriteAllText(versionJsonPath, jsonContent); return(versionJsonPath); } }
private void UpdateVersion(string projectDirectory, Repository repository, SemanticVersion oldVersion, SemanticVersion newVersion) { Requires.NotNull(projectDirectory, nameof(projectDirectory)); Requires.NotNull(repository, nameof(repository)); var signature = this.GetSignature(repository); var versionOptions = VersionFile.GetVersion(repository, projectDirectory); if (IsVersionDecrement(oldVersion, newVersion)) { this.stderr.WriteLine($"Cannot change version from {oldVersion} to {newVersion} because {newVersion} is older than {oldVersion}."); throw new ReleasePreparationException(ReleasePreparationError.VersionDecrement); } if (!EqualityComparer <SemanticVersion> .Default.Equals(versionOptions.Version, newVersion)) { if (versionOptions.VersionHeightPosition.HasValue && GitExtensions.WillVersionChangeResetVersionHeight(versionOptions.Version, newVersion, versionOptions.VersionHeightPosition.Value)) { // The version will be reset by this change, so remove the version height offset property. versionOptions.VersionHeightOffset = null; } versionOptions.Version = newVersion; var filePath = VersionFile.SetVersion(projectDirectory, versionOptions, includeSchemaProperty: true); Commands.Stage(repository, filePath); // Author a commit only if we effectively changed something. if (!repository.Head.Tip.Tree.Equals(repository.Index.WriteToTree())) { repository.Commit($"Set version to '{versionOptions.Version}'", signature, signature, new CommitOptions() { AllowEmptyCommit = false }); } } }
private Repository GetRepository(string projectDirectory) { // open git repo and use default configuration (in order to commit we need a configured user name and email // which is most likely configured on a user/system level rather than the repo level var repository = GitExtensions.OpenGitRepo(projectDirectory, useDefaultConfigSearchPaths: true); if (repository == null) { this.stderr.WriteLine($"No git repository found above directory '{projectDirectory}'."); throw new ReleasePreparationException(ReleasePreparationError.NoGitRepo); } // abort if there are any pending changes if (repository.RetrieveStatus().IsDirty) { this.stderr.WriteLine($"Uncommitted changes in directory '{projectDirectory}'."); throw new ReleasePreparationException(ReleasePreparationError.UncommittedChanges); } // check if repo is configured so we can create commits _ = this.GetSignature(repository); return(repository); }
/// <summary> /// Reads the version.txt file and returns the <see cref="Version"/> and prerelease tag from it. /// </summary> /// <param name="projectDirectory">The path to the directory which may (or its ancestors may) define the version.txt file.</param> /// <param name="actualDirectory">Set to the actual directory that the version file was found in, which may be <paramref name="projectDirectory"/> or one of its ancestors.</param> /// <returns>The version information read from the file, or <c>null</c> if the file wasn't found.</returns> public static VersionOptions GetVersion(string projectDirectory, out string actualDirectory) { Requires.NotNullOrEmpty(projectDirectory, nameof(projectDirectory)); using (var repo = GitExtensions.OpenGitRepo(projectDirectory)) { string searchDirectory = projectDirectory; while (searchDirectory != null) { string parentDirectory = Path.GetDirectoryName(searchDirectory); string versionTxtPath = Path.Combine(searchDirectory, TxtFileName); if (File.Exists(versionTxtPath)) { using (var sr = new StreamReader(File.OpenRead(versionTxtPath))) { var result = TryReadVersionFile(sr); if (result != null) { actualDirectory = searchDirectory; return(result); } } } string versionJsonPath = Path.Combine(searchDirectory, JsonFileName); if (File.Exists(versionJsonPath)) { string versionJsonContent = File.ReadAllText(versionJsonPath); var repoRelativeBaseDirectory = repo?.GetRepoRelativePath(searchDirectory); VersionOptions result = TryReadVersionJsonContent(versionJsonContent, repoRelativeBaseDirectory); if (result?.Inherit ?? false) { if (parentDirectory != null) { result = GetVersion(parentDirectory); if (result != null) { JsonConvert.PopulateObject(versionJsonContent, result, VersionOptions.GetJsonSettings( repoRelativeBaseDirectory: repoRelativeBaseDirectory)); actualDirectory = searchDirectory; return(result); } } throw new InvalidOperationException( $"\"{versionJsonPath}\" inherits from a parent directory version.json file but none exists."); } else if (result != null) { actualDirectory = searchDirectory; return(result); } } searchDirectory = parentDirectory; } } actualDirectory = null; return(null); }