void RegisterOneTag(StringBuilder errors, Commit c, string tagName, Func <Commit, ReleaseTagParsingMode> analyseInvalidTagSyntax, ref bool startingVersionForCSemVerFound) { ReleaseTagParsingMode mode = analyseInvalidTagSyntax == null ? ReleaseTagParsingMode.IgnoreMalformedTag : analyseInvalidTagSyntax(c); ReleaseTagVersion v = ReleaseTagVersion.TryParse(tagName, mode == ReleaseTagParsingMode.RaiseErrorOnMalformedTag); if (v.IsMalformed) { // Parsing in strict mode can result in malformed tag. We can not assume that here: // Debug.Assert( mode == ReleaseTagParsingMode.RaiseErrorOnMalformedTag ); if (mode == ReleaseTagParsingMode.RaiseErrorOnMalformedTag) { errors.AppendFormat("Malformed {0} on commit '{1}'.", v.ParseErrorMessage, c.Sha).AppendLine(); } return; } if (v.IsValid) { if (_startingVersionForCSemVer != null) { int cmp = _startingVersionForCSemVer.CompareTo(v); if (cmp == 0) { startingVersionForCSemVerFound = true; } else if (cmp > 0) { // This version is smaller than the StartingVersionForCSemVer: // we ignore it. return; } } if (mode == ReleaseTagParsingMode.RaiseErrorOnMalformedTagAndNonStandardPreReleaseName && v.IsPreRelease && !v.IsPreReleaseNameStandard) { errors.AppendFormat("Invalid PreRelease name in '{0}' on commit '{1}'.", v.OriginalTagText, c.Sha).AppendLine(); return; } TagCommit tagCommit; if (_collector.TryGetValue(c.Sha, out tagCommit)) { tagCommit.AddCollectedTag(v); } else { _collector.Add(c.Sha, tagCommit = new TagCommit(c, v)); } } }
/// <summary> /// Initializes a new <see cref="TagCollector"/>. /// Errors may be appended to the collector that can be syntaxic errors or multiple different versions applied to the same commit point. /// </summary> /// <param name="errors">A collector of errors. One line per error.</param> /// <param name="repo">The Git repository.</param> /// <param name="startingVersionForCSemVer">Vesion tags lower than this version will be ignored.</param> /// <param name="analyseInvalidTagSyntax"> /// Optional function that drives the behavior regarding malformed tags of commits. /// When null, <see cref="ReleaseTagParsingMode.IgnoreMalformedTag">IgnoreMalformedTag</see> is used for all tags. /// </param> /// <param name="OverriddenTags">Optional commits with associated tags that are applied as if they exist in the repository.</param> /// <param name="checkValidExistingVersions"> /// When true, existing versions are checked: one of the valid first version must exist and exisitng versions /// must be compact. /// </param> public TagCollector( StringBuilder errors, Repository repo, string startingVersionForCSemVer = null, Func <Commit, ReleaseTagParsingMode> analyseInvalidTagSyntax = null, IEnumerable <KeyValuePair <string, IReadOnlyList <string> > > OverriddenTags = null, bool checkValidExistingVersions = false) { Debug.Assert(errors != null && repo != null); _collector = new Dictionary <string, TagCommit>(); _versionsCache = new Dictionary <string, CommitVersionInfo>(); if (startingVersionForCSemVer != null) { _startingVersionForCSemVer = ReleaseTagVersion.TryParse(startingVersionForCSemVer, true); if (!_startingVersionForCSemVer.IsValid) { errors.Append("Invalid StartingVersionForCSemVer. ").Append(_startingVersionForCSemVer.ParseErrorMessage).AppendLine(); return; } } // Register all tags. RegisterAllTags(errors, repo, analyseInvalidTagSyntax, OverriddenTags); // Resolves multiple tags on the same commit. CloseCollect(errors); // Sorts TagCommit, optionally checking the existing versions. _repoVersions = new RepositoryVersions(_collector.Values, errors, _startingVersionForCSemVer, checkValidExistingVersions); // Register content. if (errors.Length == 0) { foreach (var tc in _repoVersions.TagCommits) { RegisterContent(tc); } } }