From 244b46cf7f3252d6dc3884ce184be901d1d173e5 Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Sun, 2 Sep 2018 16:12:29 -0500 Subject: Migrate WixCop into Tools from wix4. --- src/wixcop/CommandLine/ConvertCommand.cs | 212 +++++++++++++++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 src/wixcop/CommandLine/ConvertCommand.cs (limited to 'src/wixcop/CommandLine/ConvertCommand.cs') diff --git a/src/wixcop/CommandLine/ConvertCommand.cs b/src/wixcop/CommandLine/ConvertCommand.cs new file mode 100644 index 00000000..6af7d4ca --- /dev/null +++ b/src/wixcop/CommandLine/ConvertCommand.cs @@ -0,0 +1,212 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Xml; +using WixToolset.Extensibility.Data; +using WixToolset.Extensibility.Services; + +namespace WixCop.CommandLine +{ + internal class ConvertCommand : ICommandLineCommand + { + private const string SettingsFileDefault = "wixcop.settings.xml"; + + public ConvertCommand(IServiceProvider serviceProvider, bool fixErrors, int indentationAmount, List searchPatterns, bool subDirectories, string settingsFile1, string settingsFile2) + { + this.ErrorsAsWarnings = new HashSet(); + this.ExemptFiles = new HashSet(); + this.FixErrors = fixErrors; + this.IndentationAmount = indentationAmount; + this.IgnoreErrors = new HashSet(); + this.SearchPatternResults = new HashSet(); + this.SearchPatterns = searchPatterns; + this.ServiceProvider = serviceProvider; + this.SettingsFile1 = settingsFile1; + this.SettingsFile2 = settingsFile2; + this.SubDirectories = subDirectories; + } + + private HashSet ErrorsAsWarnings { get; } + + private HashSet ExemptFiles { get; } + + private bool FixErrors { get; } + + private int IndentationAmount { get; } + + private HashSet IgnoreErrors { get; } + + private HashSet SearchPatternResults { get; } + + private List SearchPatterns { get; } + + private IServiceProvider ServiceProvider { get; } + + private string SettingsFile1 { get; } + + private string SettingsFile2 { get; } + + private bool SubDirectories { get; } + + public int Execute() + { + // parse the settings if any were specified + if (null != this.SettingsFile1 || null != this.SettingsFile2) + { + this.ParseSettingsFiles(this.SettingsFile1, this.SettingsFile2); + } + else + { + if (File.Exists(ConvertCommand.SettingsFileDefault)) + { + this.ParseSettingsFiles(ConvertCommand.SettingsFileDefault, null); + } + } + + var messaging = this.ServiceProvider.GetService(); + var converter = new Converter(messaging, this.IndentationAmount, this.ErrorsAsWarnings, this.IgnoreErrors); + + var errors = this.InspectSubDirectories(converter, Path.GetFullPath(".")); + + foreach (string searchPattern in this.SearchPatterns) + { + if (!this.SearchPatternResults.Contains(searchPattern)) + { + Console.Error.WriteLine("Could not find file \"{0}\"", searchPattern); + errors++; + } + } + + return errors != 0 ? 2 : 0; + } + + /// + /// Get the files that match a search path pattern. + /// + /// The base directory at which to begin the search. + /// The search path pattern. + /// The files matching the pattern. + private static string[] GetFiles(string baseDir, string searchPath) + { + // convert alternate directory separators to the standard one + var filePath = searchPath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); + var lastSeparator = filePath.LastIndexOf(Path.DirectorySeparatorChar); + string[] files = null; + + try + { + if (0 > lastSeparator) + { + files = Directory.GetFiles(baseDir, filePath); + } + else // found directory separator + { + var searchPattern = filePath.Substring(lastSeparator + 1); + + files = Directory.GetFiles(filePath.Substring(0, lastSeparator + 1), searchPattern); + } + } + catch (DirectoryNotFoundException) + { + // don't let this function throw the DirectoryNotFoundException. (this exception + // occurs for non-existant directories and invalid characters in the searchPattern) + } + + return files; + } + + /// + /// Inspect sub-directories. + /// + /// The directory whose sub-directories will be inspected. + /// The number of errors that were found. + private int InspectSubDirectories(Converter converter, string directory) + { + var errors = 0; + + foreach (var searchPattern in this.SearchPatterns) + { + foreach (var sourceFilePath in GetFiles(directory, searchPattern)) + { + var file = new FileInfo(sourceFilePath); + + if (!this.ExemptFiles.Contains(file.Name.ToUpperInvariant())) + { + this.SearchPatternResults.Add(searchPattern); + errors += converter.ConvertFile(file.FullName, this.FixErrors); + } + } + } + + if (this.SubDirectories) + { + foreach (var childDirectoryPath in Directory.GetDirectories(directory)) + { + errors += this.InspectSubDirectories(converter, childDirectoryPath); + } + } + + return errors; + } + + /// + /// Parse the primary and secondary settings files. + /// + /// The primary settings file. + /// The secondary settings file. + private void ParseSettingsFiles(string localSettingsFile1, string localSettingsFile2) + { + if (null == localSettingsFile1 && null != localSettingsFile2) + { + throw new ArgumentException("Cannot specify a secondary settings file (set2) without a primary settings file (set1).", "localSettingsFile2"); + } + + var settingsFile = localSettingsFile1; + while (null != settingsFile) + { + XmlTextReader reader = null; + try + { + reader = new XmlTextReader(settingsFile); + var doc = new XmlDocument(); + doc.Load(reader); + + // get the types of tests that will have their errors displayed as warnings + var testsIgnoredElements = doc.SelectNodes("/Settings/IgnoreErrors/Test"); + foreach (XmlElement test in testsIgnoredElements) + { + var key = test.GetAttribute("Id"); + this.IgnoreErrors.Add(key); + } + + // get the types of tests that will have their errors displayed as warnings + var testsAsWarningsElements = doc.SelectNodes("/Settings/ErrorsAsWarnings/Test"); + foreach (XmlElement test in testsAsWarningsElements) + { + var key = test.GetAttribute("Id"); + this.ErrorsAsWarnings.Add(key); + } + + // get the exempt files + var localExemptFiles = doc.SelectNodes("/Settings/ExemptFiles/File"); + foreach (XmlElement file in localExemptFiles) + { + var key = file.GetAttribute("Name").ToUpperInvariant(); + this.ExemptFiles.Add(key); + } + } + finally + { + if (null != reader) + { + reader.Close(); + } + } + + settingsFile = localSettingsFile2; + localSettingsFile2 = null; + } + } + } +} -- cgit v1.2.3-55-g6feb