Skip to content

Commit 778d435

Browse files
committed
Propagate error code from command line execution
1 parent 1e8635f commit 778d435

File tree

11 files changed

+111
-96
lines changed

11 files changed

+111
-96
lines changed

src/CLU/Microsoft.CLU/CommandModel/ICommandModel.cs renamed to src/CLU/Microsoft.CLU.Common/ICommandModel.cs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
1-
namespace Microsoft.CLU
1+
namespace Microsoft.CLU.Common
22
{
3+
public enum CommandModelErrorCode
4+
{
5+
Success = 0,
6+
InternalFailure = -1,
7+
NonTerminatingError = 1,
8+
TerminatingError = 2,
9+
CommandNotFound = 3,
10+
11+
MissingParameters = 10,
12+
13+
PackageNotFound = 20
14+
}
15+
316
/// <summary>
417
/// The contract that different "Programming Model" model classes needs to implement.
518
/// </summary>
@@ -10,6 +23,6 @@ public interface ICommandModel
1023
/// </summary>
1124
/// <param name="commandConfiguration">Date from the command configuration file.</param>
1225
/// <param name="arguments">The command-line arguments array</param>
13-
void Run(ConfigurationDictionary commandConfiguration, string[] arguments);
26+
CommandModelErrorCode Run(ConfigurationDictionary commandConfiguration, string[] arguments);
1427
}
1528
}

src/CLU/Microsoft.CLU.Run/CommandExecMode.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,12 @@ public bool CanHandle(string[] arguments)
2727
/// IRunMode implementation for executing command.
2828
/// </summary>
2929
/// <param name="arguments">The arguments</param>
30-
public void Run(string[] arguments)
30+
public Microsoft.CLU.Common.CommandModelErrorCode Run(string[] arguments)
3131
{
3232
if (arguments.Length < 2)
3333
{
3434
CLUEnvironment.Console.WriteErrorLine(Strings.CommandExecMode_Run_MissingCommandConfigFileArgument);
35-
return;
35+
return Microsoft.CLU.Common.CommandModelErrorCode.MissingParameters;
3636
}
3737

3838
try
@@ -52,7 +52,7 @@ public void Run(string[] arguments)
5252
arguments[argsBase + 1].StartsWith("-", StringComparison.Ordinal))
5353
{
5454
CLUEnvironment.Console.WriteErrorLine(Strings.CommandExecMode_Run_MissingScriptName);
55-
return;
55+
return Microsoft.CLU.Common.CommandModelErrorCode.MissingParameters;
5656
}
5757

5858
CLUEnvironment.ScriptName = arguments[argsBase + 1];
@@ -65,7 +65,7 @@ public void Run(string[] arguments)
6565
arguments[argsBase + 1].StartsWith("-", StringComparison.Ordinal))
6666
{
6767
CLUEnvironment.Console.WriteErrorLine(Strings.CommandExecMode_Run_MissingScriptConfigFileName);
68-
return;
68+
return Microsoft.CLU.Common.CommandModelErrorCode.MissingParameters;
6969
}
7070

7171
commandConfiguration = CommandConfig.Load(arguments[argsBase + 1]);
@@ -77,7 +77,7 @@ public void Run(string[] arguments)
7777
}
7878
}
7979

80-
CommandModel.Run(commandConfiguration, GetModelArguments(arguments, argsBase));
80+
return CommandModel.Run(commandConfiguration, GetModelArguments(arguments, argsBase));
8181
}
8282
catch (TargetInvocationException tie)
8383
{
@@ -89,6 +89,8 @@ public void Run(string[] arguments)
8989
CLUEnvironment.Console.WriteErrorLine(exc.Message);
9090
CLUEnvironment.Console.WriteDebugLine($"{exc.GetType().FullName}\n{exc.StackTrace}");
9191
}
92+
93+
return Common.CommandModelErrorCode.InternalFailure;
9294
}
9395

9496
#endregion

src/CLU/Microsoft.CLU.Run/CommandModel.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,15 @@ internal class CommandModel
1919
/// </summary>
2020
/// <param name="commandConfiguration"></param>
2121
/// <param name="modelArguments"></param>
22-
public static void Run(CommandConfig commandConfiguration, string[] modelArguments)
22+
public static Microsoft.CLU.Common.CommandModelErrorCode Run(CommandConfig commandConfiguration, string[] modelArguments)
2323
{
2424
CommandModel commandModel = new CommandModel()
2525
{
2626
_commandConfiguration = commandConfiguration,
2727
_modelArguments = modelArguments
2828
};
2929
commandModel.ResolveModel();
30-
commandModel.Run();
30+
return commandModel.Run();
3131
}
3232

3333
/// <summary>
@@ -62,19 +62,21 @@ private void ResolveModel()
6262
/// <summary>
6363
/// Runs the model
6464
/// </summary>
65-
private void Run()
65+
private CommandModelErrorCode Run()
6666
{
67+
object returnValue = null;
6768
if (_entryPoint.ClassType.GetInterfaces().Where(t => String.Equals(t.FullName, Common.Constants.CommandModelInterface, StringComparison.Ordinal)).FirstOrDefault() != null)
6869
{
6970
var model = Activator.CreateInstance(_entryPoint.ClassType);
7071
var configDict = ConfigurationDictionary.Create(_commandConfiguration.Items);
71-
_entryPoint.Method.Invoke(model, new object[] { configDict, _modelArguments });
72+
returnValue = _entryPoint.Method.Invoke(model, new object[] { configDict, _modelArguments });
7273
}
7374
else
7475
{
7576
ValidateCustomEntryPoint();
76-
_entryPoint.Method.Invoke(null, new object[] { _modelArguments });
77+
returnValue = _entryPoint.Method.Invoke(null, new object[] { _modelArguments });
7778
}
79+
return (CommandModelErrorCode) returnValue;
7880
}
7981

8082
/// <summary>

src/CLU/Microsoft.CLU.Run/IRunMode.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,6 @@ internal interface IRunMode
1717
/// IRunMode implementation.
1818
/// </summary>
1919
/// <param name="arguments">The arguments</param>
20-
void Run(string[] arguments);
20+
Microsoft.CLU.Common.CommandModelErrorCode Run(string[] arguments);
2121
}
2222
}

src/CLU/Microsoft.CLU.Run/PackageManagementMode.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public bool CanHandle(string[] arguments)
3333
/// IRunMode implementation for package managment.
3434
/// </summary>
3535
/// <param name="arguments">The arguments</param>
36-
public void Run(string[] arguments)
36+
public Microsoft.CLU.Common.CommandModelErrorCode Run(string[] arguments)
3737
{
3838
_packagesRootPath = CLUEnvironment.GetPackagesRootPath();
3939
try
@@ -44,13 +44,13 @@ public void Run(string[] arguments)
4444
{
4545
CLUEnvironment.Console.WriteErrorLine(tie.InnerException.Message);
4646
CLUEnvironment.Console.WriteDebugLine($"{tie.InnerException.GetType().FullName}\n{tie.InnerException.StackTrace}");
47-
return;
47+
return Microsoft.CLU.Common.CommandModelErrorCode.InternalFailure;
4848
}
4949
catch (Exception exc)
5050
{
5151
CLUEnvironment.Console.WriteErrorLine(exc.Message);
5252
CLUEnvironment.Console.WriteDebugLine($"{exc.GetType().FullName}\n{exc.StackTrace}");
53-
return;
53+
return Microsoft.CLU.Common.CommandModelErrorCode.InternalFailure;
5454
}
5555

5656
try
@@ -77,7 +77,7 @@ public void Run(string[] arguments)
7777
arguments[argsBase + 1].StartsWith("-", StringComparison.Ordinal))
7878
{
7979
CLUEnvironment.Console.WriteLine(Strings.PackageManagementMode_Run_VersionIdMissing);
80-
return;
80+
return Microsoft.CLU.Common.CommandModelErrorCode.MissingParameters;
8181
}
8282
version = arguments[argsBase + 1];
8383
argsBase += 2;
@@ -145,12 +145,16 @@ public void Run(string[] arguments)
145145
{
146146
CLUEnvironment.Console.WriteErrorLine(tie.InnerException.Message);
147147
CLUEnvironment.Console.WriteDebugLine($"{tie.InnerException.GetType().FullName}\n{tie.InnerException.StackTrace}");
148+
return Microsoft.CLU.Common.CommandModelErrorCode.InternalFailure;
148149
}
149150
catch (Exception exc)
150151
{
151152
CLUEnvironment.Console.WriteErrorLine(exc.Message);
152153
CLUEnvironment.Console.WriteDebugLine($"{exc.GetType().FullName}\n{exc.StackTrace}");
154+
return Microsoft.CLU.Common.CommandModelErrorCode.InternalFailure;
153155
}
156+
157+
return CommandModelErrorCode.Success;
154158
}
155159

156160
/// <summary>

src/CLU/Microsoft.CLU.Run/Program.cs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@ namespace Microsoft.CLU.Run
1111
/// </summary>
1212
public class CLURun
1313
{
14+
public static void Main(string[] args) { }
15+
1416
/// <summary>
1517
/// Microsoft.CLU.Run (clurun.exe) main entry point.
1618
/// </summary>
1719
/// <param name="args">The commandline arguments</param>
18-
public static void Main(string[] args)
20+
public static Microsoft.CLU.Common.CommandModelErrorCode Execute(string[] args)
1921
{
2022
CLUEnvironment.Console = new ConsoleInputOutput(args);
2123

@@ -24,28 +26,30 @@ public static void Main(string[] args)
2426
Stopwatch sw = Stopwatch.StartNew();
2527

2628
CLURun cluRun = new CLURun();
27-
cluRun.Parse(args);
29+
var result = cluRun.Parse(args);
2830

2931
sw.Stop();
3032
CLUEnvironment.Console.WriteDebugLine($"The command executed in {sw.ElapsedMilliseconds} ms");
33+
return result;
3134
}
3235
catch (Exception exc)
3336
{
3437
CLUEnvironment.Console.WriteErrorLine(exc.Message);
3538
CLUEnvironment.Console.WriteDebugLine(exc.StackTrace);
39+
return Microsoft.CLU.Common.CommandModelErrorCode.InternalFailure;
3640
}
3741
}
3842

3943
/// <summary>
4044
/// Parse the commandline argument and bootstrap the command execution.
4145
/// </summary>
4246
/// <param name="arguments">The commandline arguments</param>
43-
private void Parse(string [] arguments)
47+
private Microsoft.CLU.Common.CommandModelErrorCode Parse(string [] arguments)
4448
{
4549
if (arguments.Count() == 0)
4650
{
4751
DisplayHelp();
48-
return;
52+
return Common.CommandModelErrorCode.MissingParameters;
4953
}
5054

5155
var mode = GetMode(arguments);
@@ -55,7 +59,7 @@ private void Parse(string [] arguments)
5559
CLUEnvironment.SetRootPaths(rootPath);
5660

5761
// Run the command.
58-
mode.Run(arguments);
62+
return mode.Run(arguments);
5963
}
6064

6165

src/CLU/Microsoft.CLU/CommandModel/BaseCommandModel.cs

Lines changed: 0 additions & 34 deletions
This file was deleted.

src/CLU/Microsoft.CLU/CommandModel/CmdletCommandModel.cs

Lines changed: 50 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ internal class CmdletCommandModel : CommandModel, ICommandModel
1919
/// </summary>
2020
/// <param name="commandConfiguration">Date from the command configuration file.</param>
2121
/// <param name="arguments">The command-line arguments array</param>
22-
public void Run(ConfigurationDictionary commandConfiguration, string[] arguments)
22+
public CommandModelErrorCode Run(ConfigurationDictionary commandConfiguration, string[] arguments)
2323
{
2424
Debug.Assert(commandConfiguration != null);
2525
Debug.Assert(arguments != null);
@@ -30,64 +30,77 @@ public void Run(ConfigurationDictionary commandConfiguration, string[] arguments
3030
}
3131

3232
Init(commandConfiguration);
33-
using (var resolver = new AssemblyResolver(CLUEnvironment.GetPackagePaths(), true))
33+
IPipe<string> pipe = new ConsolePipe(CLUEnvironment.Console);
34+
HostStreamInfo hostStreamInfo = new HostStreamInfo
3435
{
35-
IPipe<string> pipe = new ConsolePipe(CLUEnvironment.Console);
36-
HostStreamInfo hostStreamInfo = new HostStreamInfo
37-
{
38-
DataStream = new ConsoleDataStream(CLUEnvironment.Console),
39-
IsInputRedirected = CLUEnvironment.Console.IsInputRedirected,
40-
IsOutputRedirected = CLUEnvironment.Console.IsOutputRedirected,
41-
ReadFromPipe = pipe,
42-
WriteToPipe = pipe
43-
};
36+
DataStream = new ConsoleDataStream(CLUEnvironment.Console),
37+
IsInputRedirected = CLUEnvironment.Console.IsInputRedirected,
38+
IsOutputRedirected = CLUEnvironment.Console.IsOutputRedirected,
39+
ReadFromPipe = pipe,
40+
WriteToPipe = pipe
41+
};
4442

45-
// The runtime host is a Cmdlet's path to accessing system features, such as Console I/O
46-
// and session state. The runtime instance is created here and passed into the binder,
47-
// which will be creating the Cmdlet instance.
48-
var runtimeHost = new System.Management.Automation.Host.CLUHost(arguments, hostStreamInfo);
43+
// The runtime host is a Cmdlet's path to accessing system features, such as Console I/O
44+
// and session state. The runtime instance is created here and passed into the binder,
45+
// which will be creating the Cmdlet instance.
46+
var runtimeHost = new System.Management.Automation.Host.CLUHost(arguments, hostStreamInfo);
4947

50-
// Create instance of ICommandBinder and ICommand implementation for cmdlet model
51-
var binderAndCommand = new CmdletBinderAndCommand(commandConfiguration, runtimeHost);
48+
// Create instance of ICommandBinder and ICommand implementation for cmdlet model
49+
var binderAndCommand = new CmdletBinderAndCommand(commandConfiguration, runtimeHost);
5250

53-
ICommandLineParser commandParser = GetCommandLineParser();
54-
binderAndCommand.ParserSeekBackAndRun += (uint offset) =>
51+
ICommandLineParser commandParser = GetCommandLineParser();
52+
binderAndCommand.ParserSeekBackAndRun += (uint offset) =>
53+
{
54+
// Seek the parser to given offset and run.
55+
commandParser.SeekBack(offset);
56+
commandParser.Parse(binderAndCommand, arguments);
57+
};
58+
59+
if (commandParser.Parse(binderAndCommand, arguments))
60+
{
61+
binderAndCommand.ParserSeekBeginAndRun += () =>
5562
{
56-
// Seek the parser to given offset and run.
57-
commandParser.SeekBack(offset);
63+
// Seek the parser to begining and run.
64+
commandParser.SeekBegin();
5865
commandParser.Parse(binderAndCommand, arguments);
5966
};
6067

61-
if (commandParser.Parse(binderAndCommand, arguments))
68+
try
6269
{
63-
binderAndCommand.ParserSeekBeginAndRun += () =>
64-
{
65-
// Seek the parser to begining and run.
66-
commandParser.SeekBegin();
67-
commandParser.Parse(binderAndCommand, arguments);
68-
};
69-
70-
try
71-
{
7270
if (binderAndCommand.IsAsync)
7371
{
7472
binderAndCommand.InvokeAsync().Wait();
73+
7574
}
7675
else
7776
{
7877
binderAndCommand.Invoke();
7978
}
79+
80+
if (runtimeHost.NonTerminatingErrorReported)
81+
{
82+
return CommandModelErrorCode.NonTerminatingError;
83+
}
84+
else
85+
{
86+
return CommandModelErrorCode.Success;
87+
}
8088
}
81-
catch (CommandNotFoundException)
89+
catch (CommandNotFoundException)
90+
{
91+
var helplines = binderAndCommand.GenerateCommandHelp(commandParser, binderAndCommand.Discriminators.ToArray(), true);
92+
foreach (var entry in helplines)
8293
{
83-
var helplines = binderAndCommand.GenerateCommandHelp(commandParser, binderAndCommand.Discriminators.ToArray(), true);
84-
foreach (var entry in helplines)
85-
{
86-
CLUEnvironment.Console.WriteLine(entry);
87-
}
94+
CLUEnvironment.Console.WriteLine(entry);
8895
}
96+
return CommandModelErrorCode.CommandNotFound;
97+
}
98+
catch (CmdletTerminateException)
99+
{
100+
return CommandModelErrorCode.TerminatingError;
89101
}
90102
}
103+
return CommandModelErrorCode.Success;
91104
}
92105
}
93106
}

0 commit comments

Comments
 (0)