Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CLI #37

Merged
merged 13 commits into from
Apr 6, 2017
Merged

CLI #37

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,6 @@ DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html

# Click-Once directory
publish/

# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
Expand Down
12 changes: 12 additions & 0 deletions Source/NWheels.Api/Extensions/StringExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,17 @@ public static string TrimSuffix(this string source, string suffix)

return source.Substring(startIndex: 0, length: source.Length - suffix.Length);
}

//-----------------------------------------------------------------------------------------------------------------------------------------------------

public static string DefaultIfNullOrEmpty(this string source, string defaultValue)
{
if (string.IsNullOrEmpty(source))
{
return defaultValue;
}

return source;
}
}
}
1 change: 0 additions & 1 deletion Source/NWheels.Api/NWheels.Api.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
<RootNamespace>NWheels</RootNamespace>
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
<TargetFramework>netstandard1.6</TargetFramework>
<OutputPath>..\Bin\</OutputPath>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Collections.Immutable" Version="1.3.1" />
Expand Down
163 changes: 163 additions & 0 deletions Source/NWheels.Cli/CommandBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
using System;
using System.Collections.Generic;
using System.CommandLine;
using System.Diagnostics;
using System.IO;
using System.Text;

namespace NWheels.Cli
{
public abstract class CommandBase : ICommand
{
protected CommandBase(string name, string helpText)
{
this.Name = name;
this.HelpText = helpText;
}

//-----------------------------------------------------------------------------------------------------------------------------------------------------

public abstract void DefineArguments(ArgumentSyntax syntax);
public abstract void ValidateArguments(ArgumentSyntax arguments);
public abstract void Execute();

//-----------------------------------------------------------------------------------------------------------------------------------------------------

public string Name { get; }
public string HelpText { get; }

//-----------------------------------------------------------------------------------------------------------------------------------------------------

protected int ExecuteProgram(
string nameOrFilePath,
string[] args = null,
string workingDirectory = null,
bool validateExitCode = true)
{
return ExecuteProgram(
out IEnumerable<string> output,
nameOrFilePath,
args,
workingDirectory,
validateExitCode,
shouldInterceptOutput: false);
}

//-----------------------------------------------------------------------------------------------------------------------------------------------------

protected int ExecuteProgram(
out IEnumerable<string> output,
string nameOrFilePath,
string[] args = null,
string workingDirectory = null,
bool validateExitCode = true)
{
return ExecuteProgram(
out output,
nameOrFilePath,
args,
workingDirectory,
validateExitCode,
shouldInterceptOutput: true);
}

//-----------------------------------------------------------------------------------------------------------------------------------------------------

protected void Log(string message)
{
Console.WriteLine(message);
}

//-----------------------------------------------------------------------------------------------------------------------------------------------------

protected void LogDebug(string message)
{
Program.LogMessageWithColor(ConsoleColor.DarkGray, message);
}

//-----------------------------------------------------------------------------------------------------------------------------------------------------

protected void LogImportant(string message)
{
Program.LogMessageWithColor(ConsoleColor.Cyan, message);
}

//-----------------------------------------------------------------------------------------------------------------------------------------------------

protected void LogSuccess(string message)
{
Program.LogMessageWithColor(ConsoleColor.Green, message);
}

//-----------------------------------------------------------------------------------------------------------------------------------------------------

protected void LogWarning(string message)
{
Program.LogMessageWithColor(ConsoleColor.Yellow, message);
}

//-----------------------------------------------------------------------------------------------------------------------------------------------------

protected void LogError(string message)
{
Program.LogMessageWithColor(ConsoleColor.Red, message);
}

//-----------------------------------------------------------------------------------------------------------------------------------------------------

protected void ReportFatalError(Exception error)
{
Console.Error.WriteLine(error.ToString());
ReportFatalError(error.Message);
}

//-----------------------------------------------------------------------------------------------------------------------------------------------------

protected void ReportFatalError(string message)
{
LogError("FATAL ERROR: " + message);
Environment.Exit(2);
}

//-----------------------------------------------------------------------------------------------------------------------------------------------------

private int ExecuteProgram(
out IEnumerable<string> output,
string nameOrFilePath,
string[] args,
string workingDirectory,
bool validateExitCode,
bool shouldInterceptOutput)
{
var info = new ProcessStartInfo() {
FileName = nameOrFilePath,
Arguments = (args != null ? string.Join(" ", args) : string.Empty),
WorkingDirectory = workingDirectory,
RedirectStandardOutput = shouldInterceptOutput
};

var process = Process.Start(info);
List<string> outputLines = null;

if (shouldInterceptOutput)
{
outputLines = new List<string>(capacity: 100);
string line;
while ((line = process.StandardOutput.ReadLine()) != null)
{
outputLines.Add(line);
}
}

process.WaitForExit();
output = outputLines;

if (validateExitCode && process.ExitCode != 0)
{
throw new Exception($"Program '{nameOrFilePath}' failed with code {process.ExitCode}.");
}

return process.ExitCode;
}
}
}
26 changes: 26 additions & 0 deletions Source/NWheels.Cli/ICommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System;
using System.CommandLine;

namespace NWheels.Cli
{
public interface ICommand
{
void DefineArguments(ArgumentSyntax syntax);
void ValidateArguments(ArgumentSyntax arguments);
void Execute();
string Name { get; }
string HelpText { get; }
}

//---------------------------------------------------------------------------------------------------------------------------------------------------------

public static class CommandExtensions
{
public static void BindToCommandLine(this ICommand command, ArgumentSyntax syntax)
{
var commandSyntax = syntax.DefineCommand(command.Name);
commandSyntax.Help = command.HelpText;
command.DefineArguments(syntax);
}
}
}
23 changes: 23 additions & 0 deletions Source/NWheels.Cli/NWheels.Cli.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp1.1</TargetFramework>
<AssemblyName>nwheels</AssemblyName>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="System.CommandLine" Version="0.1.0-e170329-6" />
<PackageReference Include="System.Xml.XPath.XDocument" Version="4.3.0" />
<!--
<PackageReference Include="Microsoft.Build.Framework" Version="15.1.548" />
<PackageReference Include="Microsoft.NET.Sdk" Version="1.1.0-alpha-20170315-1" />
-->
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\NWheels.Api\NWheels.Api.csproj" />
<ProjectReference Include="..\NWheels.Implementation\NWheels.Implementation.csproj" />
</ItemGroup>

</Project>
81 changes: 81 additions & 0 deletions Source/NWheels.Cli/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
using System;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I run Cli without any parameters it crashed with:
"error: missing command
Press any key to continue . . ."
It seems Cli itself should gives/takes -h|--help command when there is no any.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. You're right. Will fix that.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll track it in #38. The fix will be part of PR #33.

using System.CommandLine;
using System.Linq;

namespace NWheels.Cli
{
class Program
{
private static readonly ICommand[] _s_commands = {
new Publish.PublishCommand(),
new Run.RunCommand()
};

//-----------------------------------------------------------------------------------------------------------------------------------------------------

static int Main(string[] args)
{
var arguments = ParseCommandLine(args); // will Environment.Exit with code 1 if not parsed
var activeCommand = FindActiveCommand(arguments); // will Environment.Exit with code 1 if not found
activeCommand.ValidateArguments(arguments); // will Environment.Exit with code 1 if not valid

var exitCode = 0;

try
{
activeCommand.Execute();
}
catch (Exception e)
{
LogMessageWithColor(ConsoleColor.Red, "FAILED: " + e.Message);
Console.Error.WriteLine(e.ToString());
exitCode = 2;
}

return exitCode;
}

//-----------------------------------------------------------------------------------------------------------------------------------------------------

public static void LogMessageWithColor(ConsoleColor color, string message)
{
var saveColor = Console.ForegroundColor;
Console.ForegroundColor = color;
Console.WriteLine(message);
Console.ForegroundColor = saveColor;
}

//-----------------------------------------------------------------------------------------------------------------------------------------------------

private static ArgumentSyntax ParseCommandLine(string[] args)
{
return ArgumentSyntax.Parse(args, syntax => {
foreach (var command in _s_commands)
{
command.BindToCommandLine(syntax);
}
});
}

//-----------------------------------------------------------------------------------------------------------------------------------------------------

private static ICommand FindActiveCommand(ArgumentSyntax arguments)
{
ICommand activeCommand = null;

if (arguments.ActiveCommand != null)
{
activeCommand = _s_commands
.FirstOrDefault(
c => string.Equals(c.Name, arguments.ActiveCommand.Name, StringComparison.OrdinalIgnoreCase));
}

if (activeCommand == null)
{
arguments.ReportError("Command not understood.");
}

return activeCommand;
}
}
}
9 changes: 9 additions & 0 deletions Source/NWheels.Cli/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"profiles": {
"NWheels.Cli": {
"commandName": "Project",
"commandLineArgs": "run NWheels.Samples.FirstHappyPath --no-publish",
"workingDirectory": "$(SolutionDir)"
}
}
}
Loading