public override string GetVersion() { // Get the commit at which the version number changed, and calculate the git height this.logger.LogInformation("Determining the version based on '{versionPath}' in repository '{repositoryPath}'", this.versionPath, this.gitRepository.GitDirectory); var version = VersionFile.GetVersion(Path.Combine(gitRepository.RootDirectory, this.versionPath)); this.logger.LogInformation("The current version is '{version}'", version); var pathComponents = GetPathComponents(this.versionPath); var headCommit = gitRepository.GetHeadCommit(); var commit = headCommit; Stack <GitCommit> commitsToAnalyze = new Stack <GitCommit>(); commitsToAnalyze.Push(commit); while (commitsToAnalyze.Count > 0) { // Analyze the current commit this.logger.LogDebug("Analyzing commit '{sha}'. '{commitCount}' commits to analyze.", commit.Sha, commitsToAnalyze.Count); commit = commitsToAnalyze.Peek(); if (knownGitHeights.ContainsKey(commit.Sha)) { // The same commit can be pushed to the stack if two other commits had the same parent. commitsToAnalyze.Pop(); continue; } // If this commit has a version.json file which is semantically different from the current version.json, the git height // of this commit is 1. var treeId = commit.Tree; bool versionChanged = false; for (int i = 0; i <= pathComponents.Length; i++) { if (treeId == GitObjectId.Empty) { // A version.json file was added in this revision this.logger.LogDebug("The component '{pathComponent}' could not be found in this commit. Assuming the version.json file was not present.", i == pathComponents.Length ? Array.Empty <byte>() : pathComponents[i]); versionChanged = true; break; } if (knownTreeIds.Contains(treeId)) { // Nothing changed, no need to recurse. this.logger.LogDebug("The tree ID did not change in this commit. Not inspecting the contents of the tree."); break; } knownTreeIds.Add(treeId); if (i == pathComponents.Length) { // Read the updated version information using (Stream versionStream = gitRepository.GetObjectBySha(treeId, "blob")) { var currentVersion = VersionFile.GetVersion(versionStream); this.logger.LogDebug("The version for this commit is '{version}'", currentVersion); versionChanged = currentVersion != version; if (versionChanged) { this.logger.LogInformation("The version number changed from '{version}' to '{currentVersion}' in commit '{commit}'. Using this commit as the baseline.", version, currentVersion, commit.Sha); } } } else { treeId = gitRepository.GetTreeEntry(treeId, pathComponents[i]); this.logger.LogDebug("The tree ID for '{pathComponent}' is '{treeId}'", pathComponents[i], treeId); } } if (versionChanged) { this.knownGitHeights.Add(commit.Sha, 0); var poppedCommit = commitsToAnalyze.Pop(); Debug.Assert(poppedCommit == commit); } else { bool hasParentWithUnknownGitHeight = false; int currentHeight = -1; foreach (var parent in commit.Parents) { if (knownGitHeights.ContainsKey(parent)) { var parentHeight = knownGitHeights[parent]; if (parentHeight > currentHeight) { currentHeight = parentHeight + 1; } } else { commitsToAnalyze.Push(this.gitRepository.GetCommit(parent)); hasParentWithUnknownGitHeight = true; } } if (!hasParentWithUnknownGitHeight) { // The current height of this commit is exact. this.knownGitHeights.Add(commit.Sha, currentHeight); var poppedCommit = commitsToAnalyze.Pop(); Debug.Assert(poppedCommit == commit); } } } var gitHeight = this.knownGitHeights[headCommit.Sha]; return(GetVersion(version, gitHeight)); }
public string GetVersion() { // Get the commit at which the version number changed, and calculate the git height this.logger.LogInformation("Determining the version based on '{versionPath}' in repository '{repositoryPath}'", this.versionPath, this.gitRepository.GitDirectory); var version = VersionFile.GetVersion(Path.Combine(gitRepository.RootDirectory, this.versionPath)); this.logger.LogInformation("The current version is '{version}'", version); var pathComponents = GetPathComponents(this.versionPath); var commit = gitRepository.GetHeadCommit(); string[] treeIds = new string[pathComponents.Length]; int gitHeight = 0; bool versionUpdated = false; while (!versionUpdated) { this.logger.LogDebug("Analyzing commit '{sha}'. Current git height is '{gitHeight}'", commit.Sha, gitHeight); gitHeight += 1; var treeId = commit.Tree; for (int i = 0; i < pathComponents.Length; i++) { treeId = gitRepository.GetTreeEntry(treeId, pathComponents[i]); this.logger.LogDebug("The tree ID for '{pathComponent}' is '{treeId}'", pathComponents[i], treeId); if (treeIds[i] == treeId) { // Nothing changed, no need to recurse. this.logger.LogDebug("The tree ID did not change in this commit. Not inspecting the contents of the tree."); break; } treeIds[i] = treeId; if (i == pathComponents.Length - 1) { // Read the updated version information using (Stream versionStream = gitRepository.GetObjectBySha(treeId, "blob")) { var currentVersion = VersionFile.GetVersion(versionStream); this.logger.LogDebug("The version for this commit is '{version}'", currentVersion); versionUpdated = currentVersion != version; if (versionUpdated) { this.logger.LogInformation("The version number changed from '{version}' to '{currentVersion}' in commit '{commit}'. Using this commit as the baseline.", version, currentVersion, commit.Sha); } } } } commit = gitRepository.GetCommit(commit.Parent); } return($"{version}.{gitHeight}"); }