Convert dotnet-run to System.CommandLine

This commit is contained in:
Krzysztof Wicher 2015-11-20 19:00:56 -08:00
parent 6e465818c5
commit 0ecbc0d5fc
11 changed files with 284 additions and 189 deletions

View file

@ -125,6 +125,8 @@ namespace Microsoft.DotNet.Cli.Utils
public CommandResult Execute()
{
Reporter.Verbose.WriteLine($"Running {_process.StartInfo.FileName} {_process.StartInfo.Arguments}");
ThrowIfRunning();
_running = true;

View file

@ -33,12 +33,24 @@ namespace Microsoft.DotNet.Cli.Utils
private static bool GetBool(string name, bool defaultValue = false)
{
var str = Environment.GetEnvironmentVariable(name);
bool value;
if(string.IsNullOrEmpty(str) || !bool.TryParse(str, out value))
if (string.IsNullOrEmpty(str))
{
return defaultValue;
}
return value;
switch (str.ToLowerInvariant())
{
case "true":
case "1":
case "yes":
return true;
case "false":
case "0":
case "no":
return false;
default:
return defaultValue;
}
}
}
}

View file

@ -5,7 +5,6 @@ using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.Dnx.Runtime.Common.CommandLine;
namespace Microsoft.DotNet.Cli.Utils
{

View file

@ -21,7 +21,8 @@
"Microsoft.Extensions.CommandLineUtils.Sources": {
"type": "build",
"version": "1.0.0-*"
}
},
"System.CommandLine" : "0.1.0-d111815-3"
},
"frameworks": {
"dnxcore50": { }

View file

@ -1,15 +1,9 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using Microsoft.Dnx.Runtime.Common.CommandLine;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.Extensions.ProjectModel;
using NuGet.Frameworks;
using System;
using System.CommandLine;
namespace Microsoft.DotNet.Tools.Run
{
@ -19,52 +13,24 @@ namespace Microsoft.DotNet.Tools.Run
{
DebugHelper.HandleDebugSwitch(ref args);
var app = new CommandLineApplication(throwOnUnexpectedArg: false);
app.Name = "dotnet run";
app.FullName = ".NET Executor";
app.Description = "Runner for the .NET Platform";
app.HelpOption("-h|--help");
RunCommand runCmd = new RunCommand();
var framework = app.Option("-f|--framework <FRAMEWORK>", "Compile a specific framework", CommandOptionType.MultipleValue);
var configuration = app.Option("-c|--configuration <CONFIGURATION>", "Configuration under which to build", CommandOptionType.SingleValue);
var preserveTemporaryOutput = app.Option("-t|--preserve-temporary", "Keep the output's temporary directory around", CommandOptionType.NoValue);
// This is required to be an option because otherwise we can't tell if the first argument is a project or the first argument to pass to an application
var project = app.Option("-p|--project <PROJECT_PATH>", "The path to the project to run (defaults to the current directory). Can be a path to a project.json or a project directory.", CommandOptionType.SingleValue);
app.OnExecute(() =>
ArgumentSyntax.Parse(args, syntax =>
{
// Locate the project and get the name and full path
var path = project.Value();
if (!string.IsNullOrEmpty(path))
{
if (File.Exists(path) && (Path.GetExtension(path) == ".csx"))
{
return RunInteractive(path);
}
}
else
{
path = Directory.GetCurrentDirectory();
}
syntax.HandleErrors = false;
syntax.DefineOption("f|framework", ref runCmd.Framework, "Compile a specific framework");
syntax.DefineOption("c|configuration", ref runCmd.Configuration, "Configuration under which to build");
syntax.DefineOption("t|preserve-temporary", ref runCmd.PreserveTemporary, "Keep the output's temporary directory around");
syntax.DefineOption("p|project", ref runCmd.Project, "The path to the project to run (defaults to the current directory). Can be a path to a project.json or a project directory");
var contexts = ProjectContext.CreateContextForEachFramework(path);
ProjectContext context;
if (!framework.HasValue())
{
context = contexts.First();
}
else
{
var fx = NuGetFramework.Parse(framework.Value());
context = contexts.FirstOrDefault(c => c.TargetFramework.Equals(fx));
}
return Run(context, configuration.Value() ?? Constants.DefaultConfiguration, app.RemainingArguments, preserveTemporaryOutput.HasValue());
// TODO: this is not supporting args which can be switches (i.e. --test)
// TODO: we need to make a change in System.CommandLine or parse args ourselves.
syntax.DefineParameterList("args", ref runCmd.Args, "Arguments to pass to the executable or script");
});
try
{
return app.Execute(args);
return runCmd.Start();
}
catch (Exception ex)
{
@ -76,77 +42,5 @@ namespace Microsoft.DotNet.Tools.Run
return 1;
}
}
private static int Run(ProjectContext context, string configuration, List<string> remainingArguments, bool preserveTemporaryOutput)
{
// Create a temporary directory
var tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N"));
// Compile to that directory
var result = Command.Create($"dotnet-compile", $"--output \"{tempDir}\" --temp-output \"{tempDir}\" --framework \"{context.TargetFramework}\" --configuration \"{configuration}\" {context.ProjectFile.ProjectDirectory}")
.ForwardStdOut(onlyIfVerbose: true)
.ForwardStdErr()
.Execute();
if (result.ExitCode != 0)
{
return result.ExitCode;
}
// Now launch the output and give it the results
var outputName = Path.Combine(tempDir, context.ProjectFile.Name + Constants.ExeSuffix);
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
if (context.TargetFramework.IsDesktop())
{
// Run mono if we're running a desktop target on non windows
remainingArguments.Insert(0, outputName + ".exe");
if (string.Equals(configuration, "Debug", StringComparison.OrdinalIgnoreCase))
{
// If we're compiling for the debug configuration then add the --debug flag
// other options may be passed using the MONO_OPTIONS env var
remainingArguments.Insert(0, "--debug");
}
outputName = "mono";
}
}
// Locate the runtime
string runtime = Environment.GetEnvironmentVariable("DOTNET_HOME");
if (string.IsNullOrEmpty(runtime))
{
// Use the runtime deployed with the tools, if present
var candidate = Path.Combine(AppContext.BaseDirectory, "..", "runtime");
if (File.Exists(Path.Combine(candidate, Constants.LibCoreClrName)))
{
runtime = Path.GetFullPath(candidate);
}
}
result = Command.Create(outputName, string.Join(" ", remainingArguments))
.ForwardStdOut()
.ForwardStdErr()
.EnvironmentVariable("DOTNET_HOME", runtime)
.Execute();
// Clean up
if (!preserveTemporaryOutput)
{
Directory.Delete(tempDir, recursive: true);
}
return result.ExitCode;
}
private static int RunInteractive(string scriptName)
{
var command = Command.Create($"dotnet-repl-csi", scriptName)
.ForwardStdOut()
.ForwardStdErr();
var result = command.Execute();
return result.ExitCode;
}
}
}

View file

@ -0,0 +1,154 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.Extensions.ProjectModel;
using NuGet.Frameworks;
namespace Microsoft.DotNet.Tools.Run
{
public class RunCommand
{
public string Framework = null;
public string Configuration = null;
public bool PreserveTemporary = false;
public string Project = null;
public IReadOnlyList<string> Args = null;
bool _isInteractive = false;
ProjectContext _context;
List<string> _args;
public int Start()
{
CalculateDefaultsForNonAssigned();
if (_isInteractive)
{
return RunInteractive(Project);
}
else
{
return RunExecutable();
}
}
private void CalculateDefaultsForNonAssigned()
{
if (!string.IsNullOrEmpty(Project))
{
if (File.Exists(Project) && (Path.GetExtension(Project) == ".csx"))
{
_isInteractive = true;
return;
}
}
else
{
Project = Directory.GetCurrentDirectory();
}
if (string.IsNullOrWhiteSpace(Configuration))
{
Configuration = Constants.DefaultConfiguration;
}
var contexts = ProjectContext.CreateContextForEachFramework(Project);
if (Framework == null)
{
_context = contexts.First();
}
else
{
var fx = NuGetFramework.Parse(Framework);
_context = contexts.FirstOrDefault(c => c.TargetFramework.Equals(fx));
}
if (Args == null)
{
_args = new List<string>();
}
else
{
_args = new List<string>(Args);
}
}
private int RunExecutable()
{
// Create a temporary directory
var tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N"));
// Compile to that directory
var result = Command.Create($"dotnet-compile", $"--output \"{tempDir}\" --temp-output \"{tempDir}\" --framework \"{_context.TargetFramework}\" --configuration \"{Configuration}\" {_context.ProjectFile.ProjectDirectory}")
.ForwardStdOut(onlyIfVerbose: true)
.ForwardStdErr()
.Execute();
if (result.ExitCode != 0)
{
return result.ExitCode;
}
// Now launch the output and give it the results
var outputName = Path.Combine(tempDir, _context.ProjectFile.Name + Constants.ExeSuffix);
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
if (_context.TargetFramework.IsDesktop())
{
// Run mono if we're running a desktop target on non windows
_args.Insert(0, outputName + ".exe");
if (string.Equals(Configuration, "Debug", StringComparison.OrdinalIgnoreCase))
{
// If we're compiling for the debug configuration then add the --debug flag
// other options may be passed using the MONO_OPTIONS env var
_args.Insert(0, "--debug");
}
outputName = "mono";
}
}
// Locate the runtime
string runtime = Environment.GetEnvironmentVariable("DOTNET_HOME");
if (string.IsNullOrEmpty(runtime))
{
// Use the runtime deployed with the tools, if present
var candidate = Path.Combine(AppContext.BaseDirectory, "..", "runtime");
if (File.Exists(Path.Combine(candidate, Constants.LibCoreClrName)))
{
runtime = Path.GetFullPath(candidate);
}
}
result = Command.Create(outputName, string.Join(" ", _args))
.ForwardStdOut()
.ForwardStdErr()
.EnvironmentVariable("DOTNET_HOME", runtime)
.Execute();
// Clean up
if (!PreserveTemporary)
{
Directory.Delete(tempDir, recursive: true);
}
return result.ExitCode;
}
private static int RunInteractive(string scriptName)
{
var command = Command.Create($"dotnet-repl-csi", scriptName)
.ForwardStdOut()
.ForwardStdErr();
var result = command.Execute();
return result.ExitCode;
}
}
}

View file

@ -16,11 +16,8 @@
"type": "build",
"version": "1.0.0-*"
},
"Microsoft.Extensions.CommandLineUtils.Sources": {
"type": "build",
"version": "1.0.0-*"
},
"Microsoft.Net.Compilers.netcore": "1.2.0-beta-20151117-04"
"Microsoft.Net.Compilers.netcore": "1.2.0-beta-20151117-04",
"System.CommandLine" : "0.1.0-d111815-3"
},
"frameworks": {
"dnxcore50": { }