GetVersion(string projectDir, string requiredVcs, string revisionFormat, string tagMatch, bool removeTagV, string copyright, ILogger logger, bool warnOnMissing) { // Analyse working directory RevisionData data = ProcessDirectory(projectDir, requiredVcs, tagMatch, logger); if (!string.IsNullOrEmpty(requiredVcs) && data.VcsProvider == null) { logger.Error($@"The required version control system ""{requiredVcs}"" is not available or not used in the project directory."); return(false, null, null, null); } if (string.IsNullOrEmpty(revisionFormat)) { revisionFormat = GetRevisionFormat(projectDir, logger, warnOnMissing); } if (string.IsNullOrEmpty(revisionFormat)) { revisionFormat = data.GetDefaultRevisionFormat(logger); } var rf = new RevisionFormatter { RevisionData = data, RemoveTagV = removeTagV }; try { return(true, rf.ResolveShort(revisionFormat), rf.Resolve(revisionFormat), rf.Resolve(copyright)); } catch (FormatException ex) { logger.Error(ex.Message); return(false, null, null, null); } }
/// <summary> /// Resolves all attributes in the file. /// </summary> /// <param name="rf">The revision format for the file.</param> /// <param name="simpleAttributes">Indicates whether simple version attributes are processed.</param> /// <param name="informationalAttribute">Indicates whether the AssemblyInformationalVersion attribute is processed.</param> /// <param name="revOnly">Indicates whether only the last number is replaced by the revision number.</param> /// <param name="copyrightAttribute">Indicates whether the copyright year is replaced.</param> /// <param name="echo">Indicates whether the final informational version string is displayed.</param> /// <param name="processAnyProperty">Indicates wheter all properties should be processed.</param> private void ResolveAllLines(RevisionFormatter rf, bool simpleAttributes, bool informationalAttribute, bool revOnly, bool copyrightAttribute, bool echo, bool processAnyProperty) { // Preparing a truncated dotted-numeric version if we may need it string truncVersion = null; if (simpleAttributes && !revOnly) { truncVersion = rf.ResolveShort(revisionFormat); } // Checking the revision number if we may need it int revNum = rf.RevisionData.RevisionNumber; if (revOnly) { if (revNum == 0) { // No revision number available, try to use the format as a number string revisionId = rf.Resolve(revisionFormat); if (int.TryParse(revisionId, System.Globalization.NumberStyles.None, System.Globalization.CultureInfo.InvariantCulture, out revNum)) { logger?.Trace($"Using revision number {revNum} for /revonly from format."); } } if (revNum == 0) { // Still nothing useful available logger?.Warning("Revision number is 0. Did you really mean to use /revonly?"); } if (revNum > ushort.MaxValue) { throw new ArgumentOutOfRangeException($"Revision number {revNum} is greater than {ushort.MaxValue} and cannot be used here. Consider using the offset option."); } } // Process all lines Match match; for (int i = 0; i < lines.Length; i++) { if (revOnly) { // Replace the fourth part of AssemblyVersion and AssemblyFileVersion with the // revision number. If less parts are currently specified, zeros are inserted. match = Regex.Match( lines[i], @"^(\s*\" + attrStart + @"\s*assembly\s*:\s*AssemblyVersion\s*\(\s*""[0-9]+)(\.[0-9]+)?(\.[0-9]+)?(\.[0-9]+)?(""\s*\)\s*\" + attrEnd + @".*)$", RegexOptions.IgnoreCase); if (match.Success) { lines[i] = match.Groups[1].Value + (match.Groups[2].Success ? match.Groups[2].Value : ".0") + (match.Groups[3].Success ? match.Groups[3].Value : ".0") + "." + revNum + match.Groups[5].Value; logger?.Success("Found AssemblyVersion attribute for revision number only."); } match = Regex.Match( lines[i], @"^(\s*\" + attrStart + @"\s*assembly\s*:\s*AssemblyFileVersion\s*\(\s*""[0-9]+)(\.[0-9]+)?(\.[0-9]+)?(\.[0-9]+)?(""\s*\)\s*\" + attrEnd + @".*)$", RegexOptions.IgnoreCase); if (match.Success) { lines[i] = match.Groups[1].Value + (match.Groups[2].Success ? match.Groups[2].Value : ".0") + (match.Groups[3].Success ? match.Groups[3].Value : ".0") + "." + revNum + match.Groups[5].Value; logger?.Success("Found AssemblyFileVersion attribute for revision number only."); } } if (simpleAttributes && !revOnly) { // Replace the entire version in AssemblyVersion and AssemblyFileVersion with // the truncated dotted-numeric version. match = Regex.Match( lines[i], @"^(\s*\" + attrStart + @"\s*assembly\s*:\s*AssemblyVersion\s*\(\s*"")(.*?)(""\s*\)\s*\" + attrEnd + @".*)$", RegexOptions.IgnoreCase); if (match.Success) { lines[i] = match.Groups[1].Value + truncVersion + match.Groups[3].Value; logger?.Success("Found AssemblyVersion attribute."); logger?.Trace($@" Replaced ""{match.Groups[2].Value}"" with ""{truncVersion}""."); } match = Regex.Match( lines[i], @"^(\s*\" + attrStart + @"\s*assembly\s*:\s*AssemblyFileVersion\s*\(\s*"")(.*?)(""\s*\)\s*\" + attrEnd + @".*)$", RegexOptions.IgnoreCase); if (match.Success) { lines[i] = match.Groups[1].Value + truncVersion + match.Groups[3].Value; logger?.Success("Found AssemblyFileVersion attribute."); logger?.Trace($@" Replaced ""{match.Groups[2].Value}"" with ""{truncVersion}""."); } } if (informationalAttribute && !revOnly) { // Replace the entire value of AssemblyInformationalVersion with the resolved // string of what was already there. This ignores the fallback format, should // one be given on the command line. match = Regex.Match( lines[i], @"^(\s*\" + attrStart + @"\s*assembly\s*:\s*AssemblyInformationalVersion\s*\(\s*"")(.*?)(""\s*\)\s*\" + attrEnd + @".*)$", RegexOptions.IgnoreCase); if (match.Success) { string revisionId = rf.Resolve(match.Groups[2].Value); lines[i] = match.Groups[1].Value + revisionId + match.Groups[3].Value; logger?.Success("Found AssemblyInformationalVersion attribute."); logger?.Trace($@" Replaced ""{match.Groups[2].Value}"" with ""{revisionId}""."); if (echo) { Console.WriteLine("Version: " + revisionId); } } } if (copyrightAttribute) { // Replace the entire value of Copyright with the resolved string of what was // already there. match = Regex.Match( lines[i], @"^(\s*\" + attrStart + @"\s*assembly\s*:\s*AssemblyCopyright\s*\(\s*"")(.*?)(""\s*\)\s*\" + attrEnd + @".*)$", RegexOptions.IgnoreCase); if (match.Success) { string copyrightText = rf.Resolve(match.Groups[2].Value); lines[i] = match.Groups[1].Value + copyrightText + match.Groups[3].Value; logger?.Success("Found AssemblyCopyright attribute."); logger?.Trace($@" Replaced ""{match.Groups[2].Value}"" with ""{copyrightText}""."); } } if (processAnyProperty && !string.IsNullOrEmpty(lines[i])) { string newline = rf.Resolve(lines[i]); if (newline != lines[i]) { lines[i] = newline; logger?.Trace($@" Replaced ""{lines[i]}"" with ""{newline}""."); } } } }