aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Core/CommandLine/CommandLine.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/WixToolset.Core/CommandLine/CommandLine.cs')
-rw-r--r--src/WixToolset.Core/CommandLine/CommandLine.cs210
1 files changed, 210 insertions, 0 deletions
diff --git a/src/WixToolset.Core/CommandLine/CommandLine.cs b/src/WixToolset.Core/CommandLine/CommandLine.cs
new file mode 100644
index 00000000..9aefc50a
--- /dev/null
+++ b/src/WixToolset.Core/CommandLine/CommandLine.cs
@@ -0,0 +1,210 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixToolset.Core.CommandLine
4{
5 using System;
6 using System.Collections.Generic;
7 using WixToolset.Extensibility;
8 using WixToolset.Extensibility.Data;
9 using WixToolset.Extensibility.Services;
10
11 internal enum CommandTypes
12 {
13 Unknown,
14 Build,
15 Preprocess,
16 Compile,
17 Link,
18 Bind,
19 Decompile,
20 }
21
22 internal class CommandLine : ICommandLine
23 {
24 private static readonly char[] BindPathSplit = { '=' };
25
26 public CommandLine(IServiceProvider serviceProvider)
27 {
28 this.ServiceProvider = serviceProvider;
29
30 this.Messaging = this.ServiceProvider.GetService<IMessaging>();
31 }
32
33 private IServiceProvider ServiceProvider { get; }
34
35 private IMessaging Messaging { get; set; }
36
37 public IExtensionManager ExtensionManager { get; set; }
38
39 public ICommandLineArguments Arguments { get; set; }
40
41 public static string ExpectedArgument { get; } = "expected argument";
42
43 public bool ShowHelp { get; private set; }
44
45 public ICommandLineCommand ParseStandardCommandLine()
46 {
47 var context = this.ServiceProvider.GetService<ICommandLineContext>();
48 context.ExtensionManager = this.ExtensionManager ?? this.ServiceProvider.GetService<IExtensionManager>();
49 context.Arguments = this.Arguments;
50
51 var command = this.Parse(context);
52
53 if (command.ShowLogo)
54 {
55 AppCommon.DisplayToolHeader();
56 }
57
58 return command;
59 //switch (commandType)
60 //{
61 //case CommandTypes.Build:
62 //{
63 // var sourceFiles = GatherSourceFiles(files, outputFolder);
64 // var variables = this.GatherPreprocessorVariables(defines);
65 // var bindPathList = this.GatherBindPaths(bindPaths);
66 // var filterCultures = CalculateFilterCultures(cultures);
67 // var type = CalculateOutputType(outputType, outputFile);
68 // var platform = CalculatePlatform(platformType);
69 // return new BuildCommand(this.ServiceProvider, sourceFiles, variables, locFiles, libraryFiles, filterCultures, outputFile, type, platform, cabCachePath, bindFiles, bindPathList, includePaths, intermediateFolder, contentsFile, outputsFile, builtOutputsFile);
70 //}
71
72 //case CommandTypes.Compile:
73 //{
74 // var sourceFiles = GatherSourceFiles(files, outputFolder);
75 // var variables = this.GatherPreprocessorVariables(defines);
76 // var platform = CalculatePlatform(platformType);
77 // return new CompileCommand(this.ServiceProvider, sourceFiles, variables, platform);
78 //}
79
80 //case CommandTypes.Decompile:
81 //{
82 // var sourceFiles = GatherSourceFiles(files, outputFolder);
83 // return new DecompileCommand(this.ServiceProvider, sourceFiles, outputFile);
84 //}
85 //}
86
87 //return null;
88 }
89
90 private ICommandLineCommand Parse(ICommandLineContext context)
91 {
92 var extensions = this.ExtensionManager.Create<IExtensionCommandLine>();
93
94 foreach (var extension in extensions)
95 {
96 extension.PreParse(context);
97 }
98
99 ICommandLineCommand command = null;
100 var parser = context.Arguments.Parse();
101
102 while (command?.StopParsing != true &&
103 String.IsNullOrEmpty(parser.ErrorArgument) &&
104 parser.TryGetNextSwitchOrArgument(out var arg))
105 {
106 if (String.IsNullOrWhiteSpace(arg)) // skip blank arguments.
107 {
108 continue;
109 }
110
111 // First argument must be the command or global switch (that creates a command).
112 if (command == null)
113 {
114 if (!this.TryParseUnknownCommandArg(arg, parser, out command, extensions))
115 {
116 parser.ErrorArgument = arg;
117 }
118 }
119 else if (parser.IsSwitch(arg))
120 {
121 if (!command.TryParseArgument(parser, arg) && !TryParseCommandLineArgumentWithExtension(arg, parser, extensions))
122 {
123 parser.ErrorArgument = arg;
124 }
125 }
126 else if (!TryParseCommandLineArgumentWithExtension(arg, parser, extensions) && command?.TryParseArgument(parser, arg) == false)
127 {
128 parser.ErrorArgument = arg;
129 }
130 }
131
132 foreach (var extension in extensions)
133 {
134 extension.PostParse();
135 }
136
137 return command ?? new HelpCommand();
138 }
139
140 private bool TryParseUnknownCommandArg(string arg, ICommandLineParser parser, out ICommandLineCommand command, IEnumerable<IExtensionCommandLine> extensions)
141 {
142 command = null;
143
144 if (parser.IsSwitch(arg))
145 {
146 var parameter = arg.Substring(1);
147 switch (parameter.ToLowerInvariant())
148 {
149 case "?":
150 case "h":
151 case "help":
152 command = new HelpCommand();
153 break;
154
155 case "version":
156 case "-version":
157 command = new VersionCommand();
158 break;
159 }
160 }
161 else
162 {
163 if (Enum.TryParse(arg, true, out CommandTypes commandType))
164 {
165 switch (commandType)
166 {
167 case CommandTypes.Build:
168 command = new BuildCommand(this.ServiceProvider);
169 break;
170
171 case CommandTypes.Compile:
172 command = new CompileCommand(this.ServiceProvider);
173 break;
174
175 case CommandTypes.Decompile:
176 command = new DecompileCommand(this.ServiceProvider);
177 break;
178 }
179 }
180 else
181 {
182 foreach (var extension in extensions)
183 {
184 if (extension.TryParseCommand(parser, out command))
185 {
186 break;
187 }
188
189 command = null;
190 }
191 }
192 }
193
194 return command != null;
195 }
196
197 private static bool TryParseCommandLineArgumentWithExtension(string arg, ICommandLineParser parse, IEnumerable<IExtensionCommandLine> extensions)
198 {
199 foreach (var extension in extensions)
200 {
201 if (extension.TryParseArgument(parse, arg))
202 {
203 return true;
204 }
205 }
206
207 return false;
208 }
209 }
210}