2016-06-17 16:16:09 -07: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.
2015-11-17 11:40:07 -08:00
using System ;
using System.Collections.Generic ;
using System.IO ;
2016-07-21 11:46:12 -05:00
using System.IO.Compression ;
2015-11-17 11:40:07 -08:00
using System.Linq ;
using System.Reflection ;
2016-07-21 11:46:12 -05:00
using Microsoft.DotNet.Cli.CommandLine ;
using Microsoft.DotNet.Cli.Utils ;
2016-08-09 11:05:00 -07:00
using Microsoft.DotNet.PlatformAbstractions ;
2015-11-17 11:40:07 -08:00
2015-12-03 02:16:52 -08:00
namespace Microsoft.DotNet.Tools.New
2015-11-17 11:40:07 -08:00
{
2016-01-30 21:47:50 -08:00
public class NewCommand
2015-11-17 11:40:07 -08:00
{
private static string GetFileNameFromResourceName ( string s )
{
// A.B.C.D.filename.extension
string [ ] parts = s . Split ( new char [ ] { '.' } , StringSplitOptions . RemoveEmptyEntries ) ;
if ( parts . Length < 2 )
{
return null ;
}
// filename.extension
return parts [ parts . Length - 2 ] + "." + parts [ parts . Length - 1 ] ;
}
2016-10-14 00:06:35 -07:00
public int CreateEmptyProject ( string languageName , string templateDir , bool isMsBuild )
2015-11-17 11:40:07 -08:00
{
2016-06-14 13:20:29 -07:00
// Check if project.json exists in the folder
2016-10-14 00:06:35 -07:00
if ( File . Exists ( Path . Combine ( Directory . GetCurrentDirectory ( ) , "project.json" ) ) & & ! isMsBuild )
2016-06-14 13:20:29 -07:00
{
Reporter . Error . WriteLine ( $"Creating new {languageName} project failed, project already exists." ) ;
return 1 ;
}
2016-01-30 21:47:50 -08:00
var thisAssembly = typeof ( NewCommand ) . GetTypeInfo ( ) . Assembly ;
2015-11-17 11:40:07 -08:00
var resources = from resourceName in thisAssembly . GetManifestResourceNames ( )
2015-12-26 02:46:33 +01:00
where resourceName . Contains ( templateDir )
2015-11-17 11:40:07 -08:00
select resourceName ;
2015-11-17 10:22:26 -08:00
var resourceNameToFileName = new Dictionary < string , string > ( ) ;
2015-11-17 11:40:07 -08:00
bool hasFilesToOverride = false ;
foreach ( string resourceName in resources )
{
string fileName = GetFileNameFromResourceName ( resourceName ) ;
2016-05-27 12:37:17 -07:00
using ( var resource = thisAssembly . GetManifestResourceStream ( resourceName ) )
2015-11-17 11:40:07 -08:00
{
2016-05-27 12:37:17 -07:00
var archive = new ZipArchive ( resource ) ;
try
{
2016-06-14 13:20:29 -07:00
// Check if other files from the template exists already, before extraction
IEnumerable < string > fileNames = archive . Entries . Select ( e = > e . FullName ) ;
foreach ( var entry in fileNames )
{
if ( File . Exists ( Path . Combine ( Directory . GetCurrentDirectory ( ) , entry ) ) )
{
Reporter . Error . WriteLine ( $"Creating new {languageName} project failed, directory already contains {entry}" ) ;
return 1 ;
}
}
2016-07-21 11:46:12 -05:00
string projectDirectory = Directory . GetCurrentDirectory ( ) ;
2016-05-27 12:37:17 -07:00
2016-07-21 11:46:12 -05:00
archive . ExtractToDirectory ( projectDirectory ) ;
2016-07-21 18:17:20 -05:00
ReplaceFileTemplateNames ( projectDirectory ) ;
2016-10-14 00:06:35 -07:00
if ( ! isMsBuild )
{
ReplaceProjectJsonTemplateValues ( projectDirectory ) ;
}
2016-05-27 12:37:17 -07:00
}
catch ( IOException ex )
{
Reporter . Error . WriteLine ( ex . Message ) ;
hasFilesToOverride = true ;
}
2015-11-17 11:40:07 -08:00
}
}
if ( hasFilesToOverride )
{
2015-12-26 02:46:33 +01:00
Reporter . Error . WriteLine ( $"Creating new {languageName} project failed." ) ;
2015-11-17 11:40:07 -08:00
return 1 ;
}
2015-12-26 02:46:33 +01:00
Reporter . Output . WriteLine ( $"Created new {languageName} project in {Directory.GetCurrentDirectory()}." ) ;
2015-11-17 11:40:07 -08:00
return 0 ;
}
2016-07-21 18:17:20 -05:00
private static void ReplaceProjectJsonTemplateValues ( string projectDirectory )
{
string projectJsonFile = Path . Combine ( projectDirectory , "project.json" ) ;
2016-09-27 16:29:56 -07:00
string projectJsonTemplateFile = Path . Combine ( projectDirectory , "project.json.template" ) ;
2016-07-21 18:17:20 -05:00
2016-09-27 16:29:56 -07:00
if ( File . Exists ( projectJsonTemplateFile ) )
2016-09-27 15:38:59 -07:00
{
2016-09-27 16:29:56 -07:00
File . Move ( projectJsonTemplateFile , projectJsonFile ) ;
2016-09-27 15:38:59 -07:00
}
2016-07-21 18:17:20 -05:00
}
private static void ReplaceFileTemplateNames ( string projectDirectory )
{
string projectName = new DirectoryInfo ( projectDirectory ) . Name ;
foreach ( string file in Directory . GetFiles ( projectDirectory , "*" , SearchOption . AllDirectories ) )
{
if ( Path . GetFileNameWithoutExtension ( file ) = = "$projectName$" )
{
string extension = Path . GetExtension ( file ) ;
File . Move (
file ,
Path . Combine ( Path . GetDirectoryName ( file ) , $"{projectName}{extension}" ) ) ;
}
}
}
2016-01-30 21:47:50 -08:00
public static int Run ( string [ ] args )
2015-11-17 11:40:07 -08:00
{
DebugHelper . HandleDebugSwitch ( ref args ) ;
var app = new CommandLineApplication ( ) ;
2015-12-03 02:16:52 -08:00
app . Name = "dotnet new" ;
2015-11-17 11:40:07 -08:00
app . FullName = ".NET Initializer" ;
app . Description = "Initializes empty project for .NET Platform" ;
app . HelpOption ( "-h|--help" ) ;
2016-10-14 00:06:35 -07:00
var csharp = new { Name = "C#" , Alias = new [ ] { "c#" , "cs" , "csharp" } , TemplatePrefix = "CSharp" ,
Templates = new [ ]
{
new { Name = "Console" , isMsBuild = true } ,
2016-10-17 14:45:37 -07:00
new { Name = "Web" , isMsBuild = true } ,
2016-10-14 00:06:35 -07:00
new { Name = "Lib" , isMsBuild = true } ,
new { Name = "xunittest" , isMsBuild = false } ,
new { Name = "nunittest" , isMsBuild = false }
}
} ;
var fsharp = new { Name = "F#" , Alias = new [ ] { "f#" , "fs" , "fsharp" } , TemplatePrefix = "FSharp" ,
Templates = new [ ]
{
new { Name = "Console" , isMsBuild = false } ,
new { Name = "Lib" , isMsBuild = false }
}
} ;
2016-06-23 00:20:40 +02:00
var languages = new [ ] { csharp , fsharp } ;
string langValuesString = string . Join ( ", " , languages . Select ( l = > l . Name ) ) ;
var typeValues =
from l in languages
2016-10-14 00:06:35 -07:00
let values = string . Join ( ", " , l . Templates . Select ( t = > t . Name ) )
2016-06-23 00:20:40 +02:00
select $"Valid values for {l.Name}: {values}." ;
string typeValuesString = string . Join ( " " , typeValues ) ;
var lang = app . Option ( "-l|--lang <LANGUAGE>" , $"Language of project Valid values: {langValuesString}." , CommandOptionType . SingleValue ) ;
var type = app . Option ( "-t|--type <TYPE>" , $"Type of project {typeValuesString}" , CommandOptionType . SingleValue ) ;
2015-12-26 02:46:33 +01:00
2016-01-30 21:47:50 -08:00
var dotnetNew = new NewCommand ( ) ;
2016-06-14 13:20:29 -07:00
app . OnExecute ( ( ) = >
{
2015-12-26 02:46:33 +01:00
string languageValue = lang . Value ( ) ? ? csharp . Name ;
var language = new [ ] { csharp , fsharp }
. FirstOrDefault ( l = > l . Alias . Contains ( languageValue , StringComparer . OrdinalIgnoreCase ) ) ;
if ( language = = null )
{
Reporter . Error . WriteLine ( $"Unrecognized language: {languageValue}" . Red ( ) ) ;
return - 1 ;
}
2016-10-14 00:06:35 -07:00
string typeValue = type . Value ( ) ? ? language . Templates . First ( ) . Name ;
2015-12-26 02:46:33 +01:00
2016-10-14 00:06:35 -07:00
var template = language . Templates . FirstOrDefault ( t = > StringComparer . OrdinalIgnoreCase . Equals ( typeValue , t . Name ) ) ;
if ( template = = null )
2015-12-26 02:46:33 +01:00
{
Reporter . Error . WriteLine ( $"Unrecognized type: {typeValue}" . Red ( ) ) ;
2016-07-09 19:10:54 +01:00
Reporter . Error . WriteLine ( $"Available types for {language.Name} :" . Red ( ) ) ;
2015-12-26 02:46:33 +01:00
foreach ( var t in language . Templates )
{
Reporter . Error . WriteLine ( $"- {t}" . Red ( ) ) ;
}
return - 1 ;
}
2016-10-14 00:06:35 -07:00
string templateDir = $"{language.TemplatePrefix}_{template.Name}" ;
2015-12-26 02:46:33 +01:00
2016-10-14 00:06:35 -07:00
return dotnetNew . CreateEmptyProject ( language . Name , templateDir , template . isMsBuild ) ;
2015-12-26 02:46:33 +01:00
} ) ;
2015-11-17 11:40:07 -08:00
try
{
return app . Execute ( args ) ;
}
catch ( Exception ex )
{
#if DEBUG
2015-11-17 12:06:07 -08:00
Reporter . Error . WriteLine ( ex . ToString ( ) ) ;
2015-11-17 11:40:07 -08:00
#else
2015-11-17 12:06:07 -08:00
Reporter . Error . WriteLine ( ex . Message ) ;
2015-11-17 11:40:07 -08:00
#endif
return 1 ;
}
}
}
}