public async Task Run_does_not_add_any_versions_if_no_tag_patterns_are_specified() { // ARRANGE var tags = new GitTag[] { new GitTag("1.2.3-alpha", new GitId("01")), new GitTag("4.5.6", new GitId("02")) }; var repoMock = new Mock <IGitRepository>(MockBehavior.Strict); repoMock.Setup(x => x.GetTags()).Returns(tags); var config = new ChangeLogConfiguration() { TagPatterns = Array.Empty <string>() }; var sut = new LoadVersionsFromTagsTask(m_Logger, config, repoMock.Object); // ACT var changeLog = new ApplicationChangeLog(); var result = await sut.RunAsync(changeLog); // ASSERT Assert.NotNull(changeLog.Versions); Assert.Empty(changeLog.Versions); Assert.Equal(ChangeLogTaskResult.Skipped, result); }
public async Task Task_fails_if_version_was_already_added_by_a_previous_task() { // ARRANGE var tags = new GitTag[] { new GitTag("1.2.3", new GitId("0123")), }; var repoMock = new Mock <IGitRepository>(MockBehavior.Strict); repoMock.Setup(x => x.GetTags()).Returns(tags); var sut = new LoadVersionsFromTagsTask(m_Logger, ChangeLogConfigurationLoader.GetDefaultConfiguration(), repoMock.Object); var changeLog = new ApplicationChangeLog() { new SingleVersionChangeLog(new VersionInfo(NuGetVersion.Parse("1.2.3"), new GitId("4567"))) }; // ACT var result = await sut.RunAsync(changeLog); // ASSERT Assert.Equal(ChangeLogTaskResult.Error, result); Assert.DoesNotContain(changeLog.Versions, x => x.Version == NuGetVersion.Parse("1.2.3") && x.Commit == new GitId("0123")); }
public async Task Run_adds_versions_from_tags() { // ARRANGE var tags = new GitTag[] { new GitTag("1.2.3-alpha", new GitId("01")), new GitTag("4.5.6", new GitId("02")) }; var repoMock = new Mock <IGitRepository>(MockBehavior.Strict); repoMock.Setup(x => x.GetTags()).Returns(tags); var sut = new LoadVersionsFromTagsTask(m_Logger, ChangeLogConfigurationLoader.GetDefaultConfiguration(), repoMock.Object); // ACT var changeLog = new ApplicationChangeLog(); var result = await sut.RunAsync(changeLog); // ASSERT Assert.All( tags, tag => { var version = NuGetVersion.Parse(tag.Name); Assert.Contains(new VersionInfo(version, tag.Commit), changeLog.Versions); }); Assert.Equal(ChangeLogTaskResult.Success, result); }
public async Task Run_correctly_gets_version_from_tag_name_using_default_configuration(string tagName, string version) { // ARRANGE var tags = new GitTag[] { new GitTag(tagName, new GitId("0123")), }; var repoMock = new Mock <IGitRepository>(MockBehavior.Strict); repoMock.Setup(x => x.GetTags()).Returns(tags); var expectedVersion = SemanticVersion.Parse(version); var sut = new LoadVersionsFromTagsTask(m_Logger, ChangeLogConfigurationLoader.GetDefaultConfiguration(), repoMock.Object); // ACT var changeLog = new ApplicationChangeLog(); var result = await sut.RunAsync(changeLog); // ASSERT var versionInfo = Assert.Single(changeLog.Versions); Assert.Equal(expectedVersion, versionInfo.Version); Assert.Equal(ChangeLogTaskResult.Success, result); }
public async Task Run_ignores_duplicate_versions_from_tags() { // ARRANGE var tags = new GitTag[] { new GitTag("v1.2.3", new GitId("0123")), new GitTag("4.5.6", new GitId("4567")), new GitTag("1.2.3", new GitId("8910")) }; var repoMock = new Mock <IGitRepository>(MockBehavior.Strict); repoMock.Setup(x => x.GetTags()).Returns(tags); var sut = new LoadVersionsFromTagsTask(m_Logger, ChangeLogConfigurationLoader.GetDefaultConfiguration(), repoMock.Object); // ACT var changeLog = new ApplicationChangeLog(); var result = await sut.RunAsync(changeLog); // ASSERT Assert.Contains(changeLog.Versions, x => x.Version == NuGetVersion.Parse("1.2.3") && x.Commit == new GitId("0123")); Assert.DoesNotContain(changeLog.Versions, x => x.Version == NuGetVersion.Parse("1.2.3") && x.Commit == new GitId("8910")); Assert.Equal(ChangeLogTaskResult.Success, result); }
/// <inheritdoc /> public string GetMessage(GitTag gitTag) { string[] arguments = { "show", "--format=\"%B\"", gitTag.Name }; var listValue = this.processManager.RunGit(arguments).ToList().Wait(); return(string.Join("\r\n", listValue).Trim(' ', '\r', '\n')); }
/// <summary>Compose the release note tag <paramref name="tag" /></summary> /// <param name="tag">The tag to compose a release note for</param> /// <param name="fromCommitExcluded">The last commit to include in the release note</param> /// <returns>The version description to be included in the ChangeLog</returns> private VersionDescription ComposeExistingVersionDescription(GitTag tag, string fromCommitExcluded) { var verDesc = new VersionDescription(tag); var content = this.ConcatCommitInfo(fromCommitExcluded, tag.CommitHash, Format, RefSpec); verDesc.Content.Append(content); return(verDesc); }
/// <inheritdoc /> public IObservable <string> GetMessage(GitTag gitTag) { if (gitTag == null) { throw new ArgumentNullException(nameof(gitTag)); } string[] arguments = { "show", "--format=\"%B\"", gitTag.Name }; return(_processManager.RunGit(arguments).ToList().Select(x => string.Join("\r\n", x).Trim(' ', '\r', '\n'))); }
/// <summary>Lists all tags and their commit hash</summary> /// <param name="taskBase">The MSBuild task</param> /// <param name="refSpec">The Git refSpec</param> /// <param name="sortField">The field to use when sorting the order of the tags (e.g. committerdate, v:refname, etc.)</param> /// <param name="exFatal">Whether an error is fatal</param> /// <param name="throwOnNonZeroExitCode">Whether to throw if Git returns a non-zero exit code</param> /// <returns>Map of tag name -> tag object</returns> public static Dictionary <string, GitTag> GetTagCommitMap( this GitTaskBase taskBase, string refSpec = "refs/remotes/origin/HEAD", string sortField = "committerdate", bool exFatal = true, bool throwOnNonZeroExitCode = true) { var merged = string.IsNullOrWhiteSpace(refSpec) == false ? $"--merged={refSpec}" : string.Empty; var output = taskBase.ExecuteGit($"tag -l {merged} --format=\"%(refname:strip=2) %(objecttype) %(objectname) %(object)\" --sort=\"{sortField}\"", "An exception occured while list tags and their commit hash", exFatal, throwOnNonZeroExitCode); var map = new Dictionary <string, GitTag>(); int i = 0; if (string.IsNullOrWhiteSpace(output)) { return(map); } foreach (var line in output.SplitLines(StringSplitOptions.RemoveEmptyEntries)) { var splitLine = line.Split(' '); if (splitLine.Length != 4) { throw new ToolsException($"GetTagCommitMap: tag commit list line is malformatted: '{line}'", true); } var name = splitLine[0]; var type = splitLine[1]; string commitHash; switch (type) { case "commit": commitHash = splitLine[2]; break; case "tag": default: commitHash = splitLine[3]; break; } map[name] = new GitTag(i++, name, commitHash); } return(map); }
public static object RealTargets(IParameters buildParameters) { var version = buildParameters.Required <string>("version"); var git = new GitCheckout { Repository = "git://github.com/refractalize/bounce.git", Directory = "tmp2", }; var asmInfoWithVersion = new RewriteFile { FilePath = "SolutionAssemblyInfo.cs", Rewriter = RewriteVersion(version), }; var solution = new VisualStudioSolution { SolutionPath = "Bounce.sln", DependsOn = new [] { asmInfoWithVersion } }; var frameworkProject = solution.Projects["Bounce.Framework"]; var downloadsDir = new CleanDirectory { Path = "Downloads", }; var frameworkZip = new ZipFile { Directory = frameworkProject.WhenBuilt(() => Path.GetDirectoryName(frameworkProject.OutputFile.Value)), ZipFileName = downloadsDir.Files[version.WhenBuilt(() => string.Format("Bounce.Framework.{0}.zip", version.Value))], }; var gitTag = new GitTag { Directory = ".", Tag = version.WhenBuilt(() => "v" + version.Value) }; var downloads = new All(frameworkZip, gitTag); return(new { Tests = new NUnitTests { DllPaths = solution.Projects.Select(p => p.OutputFile), }, Downloads = downloads, RewriteAsmInfo = asmInfoWithVersion, }); }
public void Parse_WithTagInformation_ExpectedTheCorrectTagObject( string inputValue, int?expectedMajor, int?expectedMinor, int?expectedPatch, int?expectedFix, string expectedPrefix, string expectedSuffix) { // Act var tagValue = GitTag.Parse(inputValue); // Assert Assert.Equal(expectedMajor, tagValue.Major); Assert.Equal(expectedMinor, tagValue.Minor); Assert.Equal(expectedPatch, tagValue.Patch); Assert.Equal(expectedFix, tagValue.Fix); Assert.Equal(expectedPrefix, tagValue.Prefix); Assert.Equal(expectedSuffix, tagValue.Suffix); Assert.Equal(inputValue, tagValue.StringValue); }
public async Task Run_ignores_tags_that_are_not_a_valid_version(string tagName) { // ARRANGE var tags = new GitTag[] { new GitTag(tagName, new GitId("01")), }; var repoMock = new Mock <IGitRepository>(MockBehavior.Strict); repoMock.Setup(x => x.GetTags()).Returns(tags); var sut = new LoadVersionsFromTagsTask(m_Logger, ChangeLogConfigurationLoader.GetDefaultConfiguration(), repoMock.Object); // ACT var changeLog = new ApplicationChangeLog(); var result = await sut.RunAsync(changeLog); // ASSERT Assert.Empty(changeLog.Versions); Assert.Equal(ChangeLogTaskResult.Success, result); }
/// <summary> /// Initializes a new instance of the <see cref="VersionGenerator"/> class. /// </summary> /// <param name="path_to_version_file">A full or relative path to a JSON version file.</param> public VersionGenerator(string path_to_version_file) { string full_version_file_path = Path.GetFullPath(path_to_version_file); FileInfo version_file_info = new FileInfo(full_version_file_path); VersionStruct versionStruct; using (StreamReader fileStream = File.OpenText(full_version_file_path)) { versionStruct = JsonSerializer.CreateDefault().Deserialize <VersionStruct>(new JsonTextReader(fileStream)); } SemVersion version_from_file; if (string.IsNullOrEmpty(versionStruct.Version) || !SemVersion.TryParse(versionStruct.Version, out version_from_file, true)) { throw new ArgumentException("Version JSON file does not contain proper Version value", "path_to_version_file"); } DirectoryInfo repository_directory = version_file_info.Directory; while (!repository_directory.GetDirectories().Where(info => info.Name == ".git").Any()) { repository_directory = repository_directory.Parent; if (repository_directory == null) { throw new ArgumentException("Version file is not contained in any git repository"); } } using (GitRepository repo = GitRepository.Create(repository_directory.FullName)) { if (repo.GetHeadCommit() == null) { throw new ArgumentException("Version file is contained in the repository without commits or git HEAD is corrupted"); } if (repo.GetAllTags().Any(t => t.Target == repo.GetHeadCommit().Value.Sha)) { GitTag commitTag = repo.GetAllTags().FirstOrDefault(t => t.Target == repo.GetHeadCommit().Value.Sha); branch_name = "tag " + commitTag.Name; } else { object head = repo.GetHeadAsReferenceOrSha(); if (head is string headName) { branch_name = headName.Substring("refs/heads/".Length); } else { branch_name = "detached HEAD"; } } StringBuilder version_string_builder = new StringBuilder(); Regex non_semver_characters_regex = new Regex(@"[^0-9A-Za-z-]+", RegexOptions.ECMAScript | RegexOptions.Compiled); string normalized_head_name = non_semver_characters_regex.Replace(branch_name, "-"); version_string_builder.Append(version_from_file.Major); version_string_builder.Append('.'); version_string_builder.Append(version_from_file.Minor); version_string_builder.Append('.'); version_string_builder.Append(version_from_file.Patch); if (!string.IsNullOrEmpty(version_from_file.Prerelease)) { version_string_builder.Append('-'); version_string_builder.Append(version_from_file.Prerelease); DateTime commit_time = repo.GetHeadCommit().Value.Committer.Date.UtcDateTime; DateTimeOffset commit_time_offset = new DateTimeOffset(commit_time); // The numerical constant here is UNIX time of January 1st, 2020 12:00 AM UTC long commit_time_in_seconds = commit_time_offset.ToUnixTimeSeconds() - 1577836800; version_string_builder.Append('.'); version_string_builder.Append(commit_time_in_seconds); version_string_builder.Append('.'); version_string_builder.Append(normalized_head_name); } version_without_build_data = version_string_builder.ToString(); version_string_builder.Append('+'); Regex codename_regex = new Regex(@"^[0-9A-Za-z-]+$", RegexOptions.ECMAScript | RegexOptions.Compiled); if (!string.IsNullOrEmpty(versionStruct.Codename) && codename_regex.IsMatch(versionStruct.Codename)) { version_string_builder.Append("codename"); version_string_builder.Append('.'); version_string_builder.Append(versionStruct.Codename); version_string_builder.Append('.'); } version_string_builder.Append("head"); version_string_builder.Append('.'); version_string_builder.Append(normalized_head_name); version_string_builder.Append('.'); version_string_builder.Append("commit"); version_string_builder.Append('.'); commit_hash = repo.GetHeadCommit().Value.Sha.ToString(); version_string_builder.Append(commit_hash); if (!string.IsNullOrEmpty(version_from_file.Build)) { version_string_builder.Append('.'); version_string_builder.Append(version_from_file.Build); } full_version = version_string_builder.ToString(); } }
public VersionDescription(GitTag gitTag) : base(gitTag.No, gitTag.Name, gitTag.CommitHash) { }
private static bool TagOnHeadIsMajorMinorPatch(GitTag tagOnHead) => tagOnHead != null && Patterns.IsCoreVersionTag.IsMatch(tagOnHead.FriendlyName);
/// <summary> /// Initializes a new instance of the <see cref="GitTagViewModel"/> class. /// </summary> /// <param name="tag">The target GitTag to Wrap.</param> public GitTagViewModel(GitTag tag) { _tag = tag ?? throw new ArgumentException($"{nameof(tag)} must not be null.", nameof(tag)); _message = tag.Message.ToProperty(this, x => x.Message, scheduler: RxApp.MainThreadScheduler); }