Exemplo n.º 1
0
        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>
        /// Patches the file and injects the revision data.
        /// </summary>
        /// <param name="patchedFileDir">The directory to save the patched AssemblyInfo file into, relative to the project directory.</param>
        /// <param name="rf">The configured revision formatter instance.</param>
        /// <param name="fallbackFormat">The fallback format if none is defined in 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>
        /// <returns>The name of the patched AssemblyInfo file.</returns>
        public string PatchFile(
            string patchedFileDir,
            RevisionFormatter rf,
            string fallbackFormat,
            bool simpleAttributes,
            bool informationalAttribute,
            bool revOnly,
            bool copyrightAttribute,
            bool echo,
            bool processAnyProperty)
        {
            logger?.Trace($@"Patching file ""{fileName}""...");
            ReadFileLines(FullFileName);

            // Find the revision format for this file
            revisionFormat = FindRevisionFormat();
            if (revisionFormat == null)
            {
                // Nothing defined in this file. Use whatever was specified on the command line or
                // found in any of the projects in the solution.
                revisionFormat = fallbackFormat;
            }
            else
            {
                logger?.Trace("The file defines a revision format: " + revisionFormat);
            }
            if (revisionFormat == null)
            {
                // If we don't have a revision format, there's nothing to replace in this file.
                return("");
            }

            // Process all lines in the file
            ResolveAllLines(rf, simpleAttributes, informationalAttribute, revOnly, copyrightAttribute, echo, processAnyProperty);

            // Write all lines to the file
            string patchedFileName = Path.Combine(patchedFileDir, "Nrt" + Path.GetFileName(fileName));

            logger?.Trace($@"Writing to file ""{patchedFileName}""...");
            Directory.CreateDirectory(Path.Combine(projectDir, patchedFileDir));
            WriteFileLines(Path.Combine(projectDir, patchedFileName));
            return(patchedFileName);
        }
        /// <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}"".");
                    }
                }
            }
        }