dotnet-installer/src/dotnet/Program.cs

277 lines
10 KiB
C#
Raw Normal View History

// 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;
2015-11-01 16:21:10 -08:00
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.DotNet.Cli.Utils;
2016-06-06 15:41:14 -07:00
using Microsoft.DotNet.Configurer;
using Microsoft.DotNet.PlatformAbstractions;
using Microsoft.DotNet.Tools.Add;
using Microsoft.DotNet.Tools.Build;
using Microsoft.DotNet.Tools.Clean;
using Microsoft.DotNet.Tools.Help;
2016-09-22 19:11:08 -05:00
using Microsoft.DotNet.Tools.Migrate;
using Microsoft.DotNet.Tools.MSBuild;
using Microsoft.DotNet.Tools.New;
2016-08-27 15:57:14 -07:00
using Microsoft.DotNet.Tools.NuGet;
using Microsoft.DotNet.Tools.Pack;
using Microsoft.DotNet.Tools.Publish;
using Microsoft.DotNet.Tools.Remove;
using Microsoft.DotNet.Tools.Restore;
using Microsoft.DotNet.Tools.RestoreProjectJson;
using Microsoft.DotNet.Tools.Run;
using Microsoft.DotNet.Tools.Test;
using Microsoft.DotNet.Tools.VSTest;
using NuGet.Frameworks;
2015-10-03 11:34:08 -07:00
namespace Microsoft.DotNet.Cli
{
public class Program
{
private static Dictionary<string, Func<string[], int>> s_builtIns = new Dictionary<string, Func<string[], int>>
{
["add"] = (new AddCommand()).Run,
["build"] = BuildCommand.Run,
["clean"] = CleanCommand.Run,
["help"] = HelpCommand.Run,
["migrate"] = MigrateCommand.Run,
["msbuild"] = MSBuildCommand.Run,
["new"] = NewCommand.Run,
2016-08-10 10:50:18 -07:00
["nuget"] = NuGetCommand.Run,
["pack"] = PackCommand.Run,
["publish"] = PublishCommand.Run,
["remove"] = (new RemoveCommand()).Run,
["restore"] = RestoreCommand.Run,
["restore-projectjson"] = RestoreProjectJsonCommand.Run,
["run"] = RunCommand.Run,
["test"] = TestCommand.Run,
["vstest"] = VSTestCommand.Run,
};
2015-10-03 11:34:08 -07:00
public static int Main(string[] args)
{
DebugHelper.HandleDebugSwitch(ref args);
2016-04-25 11:29:29 -07:00
new MulticoreJitActivator().TryActivateMulticoreJit();
2016-04-25 11:29:29 -07:00
2016-04-27 16:04:26 -07:00
if (Env.GetEnvironmentVariableAsBool("DOTNET_CLI_CAPTURE_TIMING", false))
{
PerfTrace.Enabled = true;
}
InitializeProcess();
2016-01-06 02:27:16 -08:00
try
{
2016-04-27 16:04:26 -07:00
using (PerfTrace.Current.CaptureTiming())
{
return ProcessArgs(args);
2016-04-27 16:04:26 -07:00
}
2016-01-06 02:27:16 -08:00
}
catch (GracefulException e)
2016-01-06 02:27:16 -08:00
{
Reporter.Error.WriteLine(CommandContext.IsVerbose() ? e.ToString().Red().Bold() : e.Message.Red().Bold());
2016-01-06 02:27:16 -08:00
return 1;
}
catch (Exception ex)
{
#if DEBUG
Reporter.Error.WriteLine(ex.ToString());
#else
if (Reporter.IsVerbose)
{
Reporter.Error.WriteLine(ex.ToString());
}
else
{
Reporter.Error.WriteLine(ex.Message);
}
#endif
return 1;
}
2016-04-27 16:04:26 -07:00
finally
{
if (PerfTrace.Enabled)
{
Reporter.Output.WriteLine("Performance Summary:");
PerfTraceOutput.Print(Reporter.Output, PerfTrace.GetEvents());
}
}
2016-01-06 02:27:16 -08:00
}
internal static int ProcessArgs(string[] args, ITelemetry telemetryClient = null)
2016-01-06 02:27:16 -08:00
{
2015-11-01 16:21:10 -08:00
// CommandLineApplication is a bit restrictive, so we parse things ourselves here. Individual apps should use CLA.
2016-01-06 02:27:16 -08:00
bool? verbose = null;
2016-01-06 02:27:16 -08:00
var success = true;
2015-11-01 16:21:10 -08:00
var command = string.Empty;
var lastArg = 0;
using (INuGetCacheSentinel nugetCacheSentinel = new NuGetCacheSentinel())
2015-10-08 14:49:39 -07:00
{
for (; lastArg < args.Length; lastArg++)
{
if (IsArg(args[lastArg], "v", "verbose"))
{
verbose = true;
}
else if (IsArg(args[lastArg], "version"))
{
PrintVersion();
return 0;
}
else if (IsArg(args[lastArg], "info"))
{
PrintInfo();
return 0;
}
else if (IsArg(args[lastArg], "h", "help"))
{
HelpCommand.PrintHelp();
return 0;
}
else if (args[lastArg].StartsWith("-"))
{
Reporter.Error.WriteLine($"Unknown option: {args[lastArg]}");
success = false;
}
else
{
ConfigureDotNetForFirstTimeUse(nugetCacheSentinel);
// It's the command, and we're done!
command = args[lastArg];
break;
}
}
if (!success)
2015-11-16 17:39:03 -08:00
{
HelpCommand.PrintHelp();
return 1;
2015-10-08 14:49:39 -07:00
}
if (telemetryClient == null)
2015-10-08 14:49:39 -07:00
{
telemetryClient = new Telemetry(nugetCacheSentinel);
2015-10-08 14:49:39 -07:00
}
}
2015-11-01 16:21:10 -08:00
var appArgs = (lastArg + 1) >= args.Length ? Enumerable.Empty<string>() : args.Skip(lastArg + 1).ToArray();
if (verbose.HasValue)
{
Environment.SetEnvironmentVariable(CommandContext.Variables.Verbose, verbose.ToString());
2016-04-27 16:04:26 -07:00
Console.WriteLine($"Telemetry is: {(telemetryClient.Enabled ? "Enabled" : "Disabled")}");
}
if (string.IsNullOrEmpty(command))
2015-10-08 14:49:39 -07:00
{
command = "help";
2015-11-01 16:21:10 -08:00
}
telemetryClient.TrackEvent(command, null, null);
int exitCode;
Func<string[], int> builtIn;
if (s_builtIns.TryGetValue(command, out builtIn))
{
2016-03-25 13:15:36 -07:00
exitCode = builtIn(appArgs.ToArray());
}
else
{
CommandResult result = Command.Create(
"dotnet-" + command,
appArgs,
FrameworkConstants.CommonFrameworks.NetStandardApp15)
2016-03-25 13:15:36 -07:00
.Execute();
exitCode = result.ExitCode;
}
2016-03-25 13:15:36 -07:00
return exitCode;
2015-11-01 16:21:10 -08:00
}
private static void ConfigureDotNetForFirstTimeUse(INuGetCacheSentinel nugetCacheSentinel)
{
using (PerfTrace.Current.CaptureTiming())
{
using (var nugetPackagesArchiver = new NuGetPackagesArchiver())
{
var environmentProvider = new EnvironmentProvider();
var commandFactory = new DotNetCommandFactory(alwaysRunOutOfProc: true);
var nugetCachePrimer =
new NuGetCachePrimer(commandFactory, nugetPackagesArchiver, nugetCacheSentinel);
var dotnetConfigurer = new DotnetFirstTimeUseConfigurer(
nugetCachePrimer,
nugetCacheSentinel,
environmentProvider);
dotnetConfigurer.Configure();
}
}
}
2016-04-27 16:04:26 -07:00
private static void InitializeProcess()
{
// by default, .NET Core doesn't have all code pages needed for Console apps.
// see the .NET Core Notes in https://msdn.microsoft.com/en-us/library/system.diagnostics.process(v=vs.110).aspx
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
}
internal static bool TryGetBuiltInCommand(string commandName, out Func<string[], int> builtInCommand)
{
return s_builtIns.TryGetValue(commandName, out builtInCommand);
}
private static void PrintVersion()
{
2016-03-25 13:15:36 -07:00
Reporter.Output.WriteLine(Product.Version);
}
private static void PrintInfo()
{
HelpCommand.PrintVersionHeader();
DotnetVersionFile versionFile = DotnetFiles.VersionFileObject;
var commitSha = versionFile.CommitSha ?? "N/A";
Reporter.Output.WriteLine();
Reporter.Output.WriteLine("Product Information:");
Reporter.Output.WriteLine($" Version: {Product.Version}");
Reporter.Output.WriteLine($" Commit SHA-1 hash: {commitSha}");
Reporter.Output.WriteLine();
Reporter.Output.WriteLine("Runtime Environment:");
Reporter.Output.WriteLine($" OS Name: {RuntimeEnvironment.OperatingSystem}");
Reporter.Output.WriteLine($" OS Version: {RuntimeEnvironment.OperatingSystemVersion}");
Reporter.Output.WriteLine($" OS Platform: {RuntimeEnvironment.OperatingSystemPlatform}");
Reporter.Output.WriteLine($" RID: {GetDisplayRid(versionFile)}");
Reporter.Output.WriteLine($" Base Path: {ApplicationEnvironment.ApplicationBasePath}");
}
private static bool IsArg(string candidate, string longName)
{
return IsArg(candidate, shortName: null, longName: longName);
2015-10-08 14:49:39 -07:00
}
2015-11-01 16:21:10 -08:00
private static bool IsArg(string candidate, string shortName, string longName)
2015-10-08 14:49:39 -07:00
{
return (shortName != null && candidate.Equals("-" + shortName)) || (longName != null && candidate.Equals("--" + longName));
}
private static string GetDisplayRid(DotnetVersionFile versionFile)
{
FrameworkDependencyFile fxDepsFile = new FrameworkDependencyFile();
string currentRid = RuntimeEnvironment.GetRuntimeIdentifier();
// if the current RID isn't supported by the shared framework, display the RID the CLI was
// built with instead, so the user knows which RID they should put in their "runtimes" section.
return fxDepsFile.IsRuntimeSupported(currentRid) ?
currentRid :
versionFile.BuildRid;
}
2015-10-03 11:34:08 -07:00
}
}