Convert dotnet-run to System.CommandLine
This commit is contained in:
parent
6e465818c5
commit
0ecbc0d5fc
11 changed files with 284 additions and 189 deletions
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -21,7 +21,8 @@
|
|||
"Microsoft.Extensions.CommandLineUtils.Sources": {
|
||||
"type": "build",
|
||||
"version": "1.0.0-*"
|
||||
}
|
||||
},
|
||||
"System.CommandLine" : "0.1.0-d111815-3"
|
||||
},
|
||||
"frameworks": {
|
||||
"dnxcore50": { }
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
154
src/Microsoft.DotNet.Tools.Run/RunCommand.cs
Normal file
154
src/Microsoft.DotNet.Tools.Run/RunCommand.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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": { }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue