2015-11-16 11:21:57 -08:00
// 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 ;
2016-02-18 01:09:23 -08:00
using System.IO ;
2015-10-06 02:19:27 -07:00
using System.Linq ;
2016-04-20 17:53:38 -07:00
using System.Runtime.Loader ;
2016-04-22 14:20:50 -05:00
using System.Text ;
2015-10-06 10:46:43 -07:00
using Microsoft.DotNet.Cli.Utils ;
2016-06-06 15:41:14 -07:00
using Microsoft.DotNet.Configurer ;
2016-04-28 16:30:32 -07:00
using Microsoft.DotNet.InternalAbstractions ;
2016-01-30 21:47:50 -08:00
using Microsoft.DotNet.Tools.Build ;
using Microsoft.DotNet.Tools.Compiler ;
using Microsoft.DotNet.Tools.Compiler.Csc ;
2016-02-04 12:41:50 -08:00
using Microsoft.DotNet.Tools.Help ;
2016-01-30 21:47:50 -08:00
using Microsoft.DotNet.Tools.New ;
using Microsoft.DotNet.Tools.Publish ;
2016-02-18 01:09:23 -08:00
using Microsoft.DotNet.Tools.Restore ;
2016-01-30 21:47:50 -08:00
using Microsoft.DotNet.Tools.Run ;
2016-04-14 23:33:41 -05:00
using Microsoft.DotNet.Tools.Test ;
using NuGet.Frameworks ;
2015-10-03 11:34:08 -07:00
namespace Microsoft.DotNet.Cli
{
public class Program
{
2016-04-14 23:33:41 -05:00
private static Dictionary < string , Func < string [ ] , int > > s_builtIns = new Dictionary < string , Func < string [ ] , int > >
{
["build"] = BuildCommand . Run ,
["compile-csc"] = CompileCscCommand . Run ,
["help"] = HelpCommand . Run ,
["new"] = NewCommand . Run ,
["pack"] = PackCommand . Run ,
["publish"] = PublishCommand . Run ,
["restore"] = RestoreCommand . Run ,
["run"] = RunCommand . Run ,
2016-06-17 16:16:09 -07:00
["test"] = TestCommand . Run ,
2016-07-21 11:46:12 -05:00
["build3"] = Build3Command . Run ,
["run3"] = Run3Command . Run
2016-04-14 23:33:41 -05:00
} ;
2015-10-03 11:34:08 -07:00
public static int Main ( string [ ] args )
{
2015-11-28 00:28:45 -08:00
DebugHelper . HandleDebugSwitch ( ref args ) ;
2016-04-25 11:29:29 -07:00
2016-04-22 12:23:26 -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 ;
}
2016-04-22 14:20:50 -05:00
InitializeProcess ( ) ;
2016-01-06 02:27:16 -08:00
try
{
2016-04-27 16:04:26 -07:00
using ( PerfTrace . Current . CaptureTiming ( ) )
{
2016-06-22 15:17:54 -07:00
return ProcessArgs ( args ) ;
2016-04-27 16:04:26 -07:00
}
2016-01-06 02:27:16 -08:00
}
2016-04-12 16:44:34 -07:00
catch ( GracefulException e )
2016-01-06 02:27:16 -08:00
{
2016-04-29 15:46:16 -05:00
Reporter . Error . WriteLine ( CommandContext . IsVerbose ( ) ? e . ToString ( ) . Red ( ) . Bold ( ) : e . Message . Red ( ) . Bold ( ) ) ;
2016-04-28 17:49:04 -07:00
2016-01-06 02:27:16 -08:00
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
}
2016-06-22 15:17:54 -07: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
2016-02-05 12:55:09 -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 ;
2016-06-22 15:17:54 -07:00
using ( INuGetCacheSentinel nugetCacheSentinel = new NuGetCacheSentinel ( ) )
2015-10-08 14:49:39 -07:00
{
2016-06-22 15:17:54 -07:00
for ( ; lastArg < args . Length ; lastArg + + )
2015-12-18 16:39:43 -08:00
{
2016-06-22 15:17:54 -07:00
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 ;
}
2015-12-18 16:39:43 -08:00
}
2016-06-22 15:17:54 -07:00
if ( ! success )
2015-11-16 17:39:03 -08:00
{
2016-02-04 12:41:50 -08:00
HelpCommand . PrintHelp ( ) ;
2016-06-22 15:17:54 -07:00
return 1 ;
2015-10-08 14:49:39 -07:00
}
2016-06-22 15:17:54 -07:00
if ( telemetryClient = = null )
2015-10-08 14:49:39 -07:00
{
2016-06-22 15:17:54 -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 ( ) ;
2016-02-05 12:55:09 -08:00
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 ")}" ) ;
2016-02-05 12:55:09 -08:00
}
2016-02-04 12:41:50 -08:00
if ( string . IsNullOrEmpty ( command ) )
2015-10-08 14:49:39 -07:00
{
2016-02-04 12:41:50 -08:00
command = "help" ;
2015-11-01 16:21:10 -08:00
}
2016-04-27 17:28:44 -07:00
telemetryClient . TrackEvent ( command , null , null ) ;
2016-04-22 15:01:56 -07:00
int exitCode ;
2016-01-30 21:47:50 -08:00
Func < string [ ] , int > builtIn ;
2016-04-14 23:33:41 -05:00
if ( s_builtIns . TryGetValue ( command , out builtIn ) )
2016-01-30 21:47:50 -08:00
{
2016-03-25 13:15:36 -07:00
exitCode = builtIn ( appArgs . ToArray ( ) ) ;
}
else
{
CommandResult result = Command . Create ( "dotnet-" + command , appArgs , FrameworkConstants . CommonFrameworks . NetStandardApp15 )
. Execute ( ) ;
exitCode = result . ExitCode ;
2016-01-30 21:47:50 -08:00
}
2016-03-25 13:15:36 -07:00
return exitCode ;
2015-11-01 16:21:10 -08:00
}
2016-06-22 15:17:54 -07:00
private static void ConfigureDotNetForFirstTimeUse ( INuGetCacheSentinel nugetCacheSentinel )
2016-06-09 20:52:49 -07:00
{
2016-06-10 13:02:48 -07:00
using ( PerfTrace . Current . CaptureTiming ( ) )
2016-06-09 20:52:49 -07:00
{
2016-06-10 13:02:48 -07:00
using ( var nugetPackagesArchiver = new NuGetPackagesArchiver ( ) )
{
2016-06-22 15:17:54 -07:00
var environmentProvider = new EnvironmentProvider ( ) ;
var commandFactory = new DotNetCommandFactory ( ) ;
var nugetCachePrimer =
new NuGetCachePrimer ( commandFactory , nugetPackagesArchiver , nugetCacheSentinel ) ;
var dotnetConfigurer = new DotnetFirstTimeUseConfigurer (
nugetCachePrimer ,
nugetCacheSentinel ,
environmentProvider ) ;
dotnetConfigurer . Configure ( ) ;
2016-06-10 13:02:48 -07:00
}
}
2016-06-09 20:52:49 -07:00
}
2016-04-27 16:04:26 -07:00
2016-04-22 14:20:50 -05: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 ) ;
}
2016-04-14 23:33:41 -05:00
internal static bool TryGetBuiltInCommand ( string commandName , out Func < string [ ] , int > builtInCommand )
{
return s_builtIns . TryGetValue ( commandName , out builtInCommand ) ;
}
2016-03-28 17:17:21 -07:00
private static void PrintVersion ( )
2016-03-24 15:36:58 -05:00
{
2016-03-25 13:15:36 -07:00
Reporter . Output . WriteLine ( Product . Version ) ;
2016-03-24 15:36:58 -05:00
}
private static void PrintInfo ( )
2015-12-18 16:39:43 -08:00
{
2016-02-04 12:41:50 -08:00
HelpCommand . PrintVersionHeader ( ) ;
2015-12-18 16:39:43 -08:00
2016-02-19 20:01:14 -08:00
var commitSha = GetCommitSha ( ) ? ? "N/A" ;
2016-02-18 01:09:23 -08:00
Reporter . Output . WriteLine ( ) ;
Reporter . Output . WriteLine ( "Product Information:" ) ;
2016-05-04 18:02:52 +00:00
Reporter . Output . WriteLine ( $" Version: {Product.Version}" ) ;
Reporter . Output . WriteLine ( $" Commit SHA-1 hash: {commitSha}" ) ;
2016-02-18 01:09:23 -08:00
Reporter . Output . WriteLine ( ) ;
2015-12-18 16:39:43 -08:00
Reporter . Output . WriteLine ( "Runtime Environment:" ) ;
2016-04-28 16:30:32 -07:00
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: {RuntimeEnvironment.GetRuntimeIdentifier()}" ) ;
2015-12-18 16:39:43 -08:00
}
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
{
2015-12-18 16:39:43 -08:00
return ( shortName ! = null & & candidate . Equals ( "-" + shortName ) ) | | ( longName ! = null & & candidate . Equals ( "--" + longName ) ) ;
2015-10-06 02:19:27 -07:00
}
2016-04-22 15:01:56 -07:00
2016-02-18 01:09:23 -08:00
private static string GetCommitSha ( )
{
2016-03-03 22:57:43 -08:00
var versionFile = DotnetFiles . VersionFile ;
2016-04-22 15:01:56 -07:00
2016-02-18 01:09:23 -08:00
if ( File . Exists ( versionFile ) )
{
2016-02-19 20:01:14 -08:00
return File . ReadLines ( versionFile ) . FirstOrDefault ( ) ? . Substring ( 0 , 10 ) ;
2016-02-18 01:09:23 -08:00
}
2016-04-22 15:01:56 -07:00
2016-02-18 01:09:23 -08:00
return null ;
}
2015-10-03 11:34:08 -07:00
}
}