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
{
2016-12-05 01:03:33 -08:00
Reporter . Error . WriteLine ( String . Format ( LocalizableStrings . CreatingNewError , languageName ) ) ;
2016-06-14 13:20:29 -07:00
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 ) ) )
{
2016-12-05 10:23:34 -08:00
Reporter . Error . WriteLine ( LocalizableStrings . ProjectContainsError , languageName , entry ) ;
2016-06-14 13:20:29 -07:00
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 )
{
2016-12-05 10:23:34 -08:00
Reporter . Error . WriteLine ( LocalizableStrings . ProjectFailedError , languageName ) ;
2015-11-17 11:40:07 -08:00
return 1 ;
}
2016-12-05 10:23:34 -08:00
Reporter . Output . WriteLine ( LocalizableStrings . CreatedNewProject , languageName , 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" ;
2016-12-04 23:18:56 -08:00
app . FullName = LocalizableStrings . AppFullName ;
app . Description = LocalizableStrings . AppDescription ;
2015-11-17 11:40:07 -08:00
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-28 10:22:22 -07:00
new { Name = "Lib" , isMsBuild = true } ,
2016-11-02 13:44:28 -10:00
new { Name = "Mstest" , isMsBuild = true } ,
new { Name = "Xunittest" , isMsBuild = true }
2016-10-14 00:06:35 -07:00
}
} ;
2016-11-24 07:57:54 +01:00
var fsharp = new { Name = "F#" , Alias = new [ ] { "f#" , "fs" , "fsharp" } , TemplatePrefix = "FSharp" ,
Templates = new [ ]
{
new { Name = "Console" , isMsBuild = true } ,
new { Name = "Web" , isMsBuild = true } ,
new { Name = "Lib" , isMsBuild = true } ,
new { Name = "Mstest" , isMsBuild = true } ,
new { Name = "Xunittest" , isMsBuild = true }
}
} ;
var languages = new [ ] { csharp , fsharp } ;
2016-06-23 00:20:40 +02:00
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-12-04 23:18:56 -08:00
select $"{LocalizableStrings.ValidValuesText}{l.Name}: {values}." ;
2016-06-23 00:20:40 +02:00
string typeValuesString = string . Join ( " " , typeValues ) ;
2016-12-04 23:18:56 -08:00
var lang = app . Option (
$"-l|--lang <{LocalizableStrings.Language}>" ,
$"{LocalizableStrings.LanguageOfProject} {LocalizableStrings.ValidValues}: {langValuesString}." ,
CommandOptionType . SingleValue ) ;
var type = app . Option (
$"-t|--type <{LocalizableStrings.Type}>" ,
$"{LocalizableStrings.TypeOfProject} {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 ;
2016-11-24 07:57:54 +01:00
var language = languages
2015-12-26 02:46:33 +01:00
. FirstOrDefault ( l = > l . Alias . Contains ( languageValue , StringComparer . OrdinalIgnoreCase ) ) ;
if ( language = = null )
{
2016-12-04 23:18:56 -08:00
Reporter . Error . WriteLine ( $"{LocalizableStrings.UnrecognizedLanguage}: {languageValue}" . Red ( ) ) ;
2015-12-26 02:46:33 +01:00
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
{
2016-12-05 10:23:34 -08:00
Reporter . Error . WriteLine ( ( LocalizableStrings . UnrecognizedType , typeValue ) . Red ( ) ) ;
Reporter . Error . WriteLine ( LocalizableStrings . AvailableTypes , 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 ;
}
}
}
}