aboutsummaryrefslogtreecommitdiff
path: root/src/wixcop/CommandLine/ConvertCommand.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/wixcop/CommandLine/ConvertCommand.cs')
-rw-r--r--src/wixcop/CommandLine/ConvertCommand.cs212
1 files changed, 212 insertions, 0 deletions
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 @@
1using System;
2using System.Collections.Generic;
3using System.IO;
4using System.Linq;
5using System.Xml;
6using WixToolset.Extensibility.Data;
7using WixToolset.Extensibility.Services;
8
9namespace WixCop.CommandLine
10{
11 internal class ConvertCommand : ICommandLineCommand
12 {
13 private const string SettingsFileDefault = "wixcop.settings.xml";
14
15 public ConvertCommand(IServiceProvider serviceProvider, bool fixErrors, int indentationAmount, List<string> searchPatterns, bool subDirectories, string settingsFile1, string settingsFile2)
16 {
17 this.ErrorsAsWarnings = new HashSet<string>();
18 this.ExemptFiles = new HashSet<string>();
19 this.FixErrors = fixErrors;
20 this.IndentationAmount = indentationAmount;
21 this.IgnoreErrors = new HashSet<string>();
22 this.SearchPatternResults = new HashSet<string>();
23 this.SearchPatterns = searchPatterns;
24 this.ServiceProvider = serviceProvider;
25 this.SettingsFile1 = settingsFile1;
26 this.SettingsFile2 = settingsFile2;
27 this.SubDirectories = subDirectories;
28 }
29
30 private HashSet<string> ErrorsAsWarnings { get; }
31
32 private HashSet<string> ExemptFiles { get; }
33
34 private bool FixErrors { get; }
35
36 private int IndentationAmount { get; }
37
38 private HashSet<string> IgnoreErrors { get; }
39
40 private HashSet<string> SearchPatternResults { get; }
41
42 private List<string> SearchPatterns { get; }
43
44 private IServiceProvider ServiceProvider { get; }
45
46 private string SettingsFile1 { get; }
47
48 private string SettingsFile2 { get; }
49
50 private bool SubDirectories { get; }
51
52 public int Execute()
53 {
54 // parse the settings if any were specified
55 if (null != this.SettingsFile1 || null != this.SettingsFile2)
56 {
57 this.ParseSettingsFiles(this.SettingsFile1, this.SettingsFile2);
58 }
59 else
60 {
61 if (File.Exists(ConvertCommand.SettingsFileDefault))
62 {
63 this.ParseSettingsFiles(ConvertCommand.SettingsFileDefault, null);
64 }
65 }
66
67 var messaging = this.ServiceProvider.GetService<IMessaging>();
68 var converter = new Converter(messaging, this.IndentationAmount, this.ErrorsAsWarnings, this.IgnoreErrors);
69
70 var errors = this.InspectSubDirectories(converter, Path.GetFullPath("."));
71
72 foreach (string searchPattern in this.SearchPatterns)
73 {
74 if (!this.SearchPatternResults.Contains(searchPattern))
75 {
76 Console.Error.WriteLine("Could not find file \"{0}\"", searchPattern);
77 errors++;
78 }
79 }
80
81 return errors != 0 ? 2 : 0;
82 }
83
84 /// <summary>
85 /// Get the files that match a search path pattern.
86 /// </summary>
87 /// <param name="baseDir">The base directory at which to begin the search.</param>
88 /// <param name="searchPath">The search path pattern.</param>
89 /// <returns>The files matching the pattern.</returns>
90 private static string[] GetFiles(string baseDir, string searchPath)
91 {
92 // convert alternate directory separators to the standard one
93 var filePath = searchPath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
94 var lastSeparator = filePath.LastIndexOf(Path.DirectorySeparatorChar);
95 string[] files = null;
96
97 try
98 {
99 if (0 > lastSeparator)
100 {
101 files = Directory.GetFiles(baseDir, filePath);
102 }
103 else // found directory separator
104 {
105 var searchPattern = filePath.Substring(lastSeparator + 1);
106
107 files = Directory.GetFiles(filePath.Substring(0, lastSeparator + 1), searchPattern);
108 }
109 }
110 catch (DirectoryNotFoundException)
111 {
112 // don't let this function throw the DirectoryNotFoundException. (this exception
113 // occurs for non-existant directories and invalid characters in the searchPattern)
114 }
115
116 return files;
117 }
118
119 /// <summary>
120 /// Inspect sub-directories.
121 /// </summary>
122 /// <param name="directory">The directory whose sub-directories will be inspected.</param>
123 /// <returns>The number of errors that were found.</returns>
124 private int InspectSubDirectories(Converter converter, string directory)
125 {
126 var errors = 0;
127
128 foreach (var searchPattern in this.SearchPatterns)
129 {
130 foreach (var sourceFilePath in GetFiles(directory, searchPattern))
131 {
132 var file = new FileInfo(sourceFilePath);
133
134 if (!this.ExemptFiles.Contains(file.Name.ToUpperInvariant()))
135 {
136 this.SearchPatternResults.Add(searchPattern);
137 errors += converter.ConvertFile(file.FullName, this.FixErrors);
138 }
139 }
140 }
141
142 if (this.SubDirectories)
143 {
144 foreach (var childDirectoryPath in Directory.GetDirectories(directory))
145 {
146 errors += this.InspectSubDirectories(converter, childDirectoryPath);
147 }
148 }
149
150 return errors;
151 }
152
153 /// <summary>
154 /// Parse the primary and secondary settings files.
155 /// </summary>
156 /// <param name="localSettingsFile1">The primary settings file.</param>
157 /// <param name="localSettingsFile2">The secondary settings file.</param>
158 private void ParseSettingsFiles(string localSettingsFile1, string localSettingsFile2)
159 {
160 if (null == localSettingsFile1 && null != localSettingsFile2)
161 {
162 throw new ArgumentException("Cannot specify a secondary settings file (set2) without a primary settings file (set1).", "localSettingsFile2");
163 }
164
165 var settingsFile = localSettingsFile1;
166 while (null != settingsFile)
167 {
168 XmlTextReader reader = null;
169 try
170 {
171 reader = new XmlTextReader(settingsFile);
172 var doc = new XmlDocument();
173 doc.Load(reader);
174
175 // get the types of tests that will have their errors displayed as warnings
176 var testsIgnoredElements = doc.SelectNodes("/Settings/IgnoreErrors/Test");
177 foreach (XmlElement test in testsIgnoredElements)
178 {
179 var key = test.GetAttribute("Id");
180 this.IgnoreErrors.Add(key);
181 }
182
183 // get the types of tests that will have their errors displayed as warnings
184 var testsAsWarningsElements = doc.SelectNodes("/Settings/ErrorsAsWarnings/Test");
185 foreach (XmlElement test in testsAsWarningsElements)
186 {
187 var key = test.GetAttribute("Id");
188 this.ErrorsAsWarnings.Add(key);
189 }
190
191 // get the exempt files
192 var localExemptFiles = doc.SelectNodes("/Settings/ExemptFiles/File");
193 foreach (XmlElement file in localExemptFiles)
194 {
195 var key = file.GetAttribute("Name").ToUpperInvariant();
196 this.ExemptFiles.Add(key);
197 }
198 }
199 finally
200 {
201 if (null != reader)
202 {
203 reader.Close();
204 }
205 }
206
207 settingsFile = localSettingsFile2;
208 localSettingsFile2 = null;
209 }
210 }
211 }
212}