예제 #1
0
        /// <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);
        }