2016-01-04 12:36:46 -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 ;
using System.Collections.Generic ;
using System.IO ;
using System.Linq ;
using System.Text ;
using Microsoft.DotNet.Cli.Utils ;
using Microsoft.DotNet.Cli.Compiler.Common ;
using Microsoft.Dnx.Runtime.Common.CommandLine ;
using Microsoft.DotNet.ProjectModel ;
using Microsoft.DotNet.ProjectModel.Graph ;
using NuGet.Frameworks ;
2015-12-18 16:39:43 -08:00
using Microsoft.Extensions.PlatformAbstractions ;
2016-01-04 12:36:46 -08:00
namespace Microsoft.DotNet.Tools.Restore
{
public class Program
{
2015-12-18 16:39:43 -08:00
private static readonly string DefaultRid = PlatformServices . Default . Runtime . GetLegacyRestoreRuntimeIdentifier ( ) ;
2016-01-04 12:36:46 -08:00
public static int Main ( string [ ] args )
{
DebugHelper . HandleDebugSwitch ( ref args ) ;
var app = new CommandLineApplication ( false )
{
Name = "dotnet restore" ,
FullName = ".NET project dependency restorer" ,
Description = "Restores dependencies listed in project.json"
} ;
app . OnExecute ( ( ) = >
{
try
{
var projectRestoreResult = Dnx . RunRestore ( args ) ;
var restoreTasks = GetRestoreTasks ( args ) ;
foreach ( var restoreTask in restoreTasks )
{
var project = ProjectReader . GetProject ( restoreTask . ProjectPath ) ;
2016-01-06 02:27:16 -08:00
RestoreTools ( project , restoreTask ) ;
2016-01-04 12:36:46 -08:00
}
return projectRestoreResult ;
}
catch ( InvalidOperationException e )
{
Console . WriteLine ( e . Message ) ;
return - 1 ;
}
catch ( Exception e )
{
Console . WriteLine ( e . Message ) ;
return - 2 ;
}
} ) ;
return app . Execute ( args ) ;
}
private static IEnumerable < RestoreTask > GetRestoreTasks ( IEnumerable < string > args )
{
var directory = Directory . GetCurrentDirectory ( ) ;
if ( args . Any ( ) )
{
var firstArg = args . First ( ) ;
if ( IsProjectFile ( firstArg ) )
{
return new [ ] { new RestoreTask { ProjectPath = firstArg , Arguments = args . Skip ( 1 ) } } ;
}
if ( Directory . Exists ( firstArg ) )
{
directory = firstArg ;
args = args . Skip ( 1 ) ;
}
}
return GetAllProjectFiles ( directory )
. Select ( p = > new RestoreTask { ProjectPath = p , Arguments = args } ) ;
}
private static string [ ] GetAllProjectFiles ( string directory )
{
return Directory . GetFiles ( directory , Project . FileName , SearchOption . AllDirectories ) ;
}
private static bool IsProjectFile ( string firstArg )
{
return firstArg . EndsWith ( Project . FileName ) & & File . Exists ( firstArg ) ;
}
2016-01-06 02:27:16 -08:00
private static void RestoreTools ( Project project , RestoreTask restoreTask )
2016-01-04 12:36:46 -08:00
{
foreach ( var tooldep in project . Tools )
{
2016-01-06 02:27:16 -08:00
RestoreTool ( tooldep , restoreTask ) ;
2016-01-04 12:36:46 -08:00
}
}
2016-01-06 02:27:16 -08:00
private static void RestoreTool ( LibraryRange tooldep , RestoreTask restoreTask )
2016-01-04 12:36:46 -08:00
{
2016-01-06 02:27:16 -08:00
var tempPath = Path . Combine ( restoreTask . ProjectDirectory , Guid . NewGuid ( ) . ToString ( ) , "bin" ) ;
2016-01-04 12:36:46 -08:00
2016-01-06 02:27:16 -08:00
RestoreToolToPath ( tooldep , restoreTask . Arguments , tempPath ) ;
2016-01-04 12:36:46 -08:00
CreateDepsInPackageCache ( tooldep , tempPath ) ;
2016-01-06 02:27:16 -08:00
PersistLockFile ( tooldep , tempPath , restoreTask . ProjectDirectory ) ;
2016-01-04 12:36:46 -08:00
Directory . Delete ( tempPath , true ) ;
}
2016-01-06 02:27:16 -08:00
private static void PersistLockFile ( LibraryRange tooldep , string tempPath , string projectPath )
2016-01-04 12:36:46 -08:00
{
2016-01-06 02:27:16 -08:00
var sourcePath = Path . Combine ( tempPath , "project.lock.json" ) ;
var targetDir = Path . Combine ( projectPath , "artifacts" , "Tools" , tooldep . Name ) ;
var targetPath = Path . Combine ( targetDir , "project.lock.json" ) ;
if ( Directory . Exists ( targetDir ) ) Directory . Delete ( targetDir , true ) ;
Directory . CreateDirectory ( targetDir ) ;
Console . WriteLine ( $"Writing '{sourcePath}' to '{targetPath}'" ) ;
File . Move ( sourcePath , targetPath ) ;
2016-01-04 12:36:46 -08:00
}
private static void CreateDepsInPackageCache ( LibraryRange toolLibrary , string projectPath )
{
var context = ProjectContext . Create ( projectPath ,
2015-12-18 16:39:43 -08:00
FrameworkConstants . CommonFrameworks . DnxCore50 , new [ ] { DefaultRid } ) ;
2016-01-04 12:36:46 -08:00
var toolDescription = context . LibraryManager . GetLibraries ( )
. Select ( l = > l as PackageDescription )
. Where ( l = > l ! = null )
. FirstOrDefault ( l = > l . Identity . Name = = toolLibrary . Name ) ;
var depsPath = Path . Combine (
toolDescription . Path ,
Path . GetDirectoryName ( toolDescription . Target . RuntimeAssemblies . First ( ) . Path ) ,
toolDescription . Identity . Name + FileNameSuffixes . Deps ) ;
context . MakeCompilationOutputRunnable ( context . ProjectDirectory , Constants . DefaultConfiguration ) ;
if ( File . Exists ( depsPath ) ) File . Delete ( depsPath ) ;
File . Move ( Path . Combine ( context . ProjectDirectory , "bin" + FileNameSuffixes . Deps ) , depsPath ) ;
}
private static void RestoreToolToPath ( LibraryRange tooldep , IEnumerable < string > args , string tempPath )
{
Directory . CreateDirectory ( tempPath ) ;
var projectPath = Path . Combine ( tempPath , Project . FileName ) ;
2016-01-06 02:27:16 -08:00
Console . WriteLine ( $"Restoring Tool '{tooldep.Name}' for '{projectPath}' in '{tempPath}'" ) ;
2016-01-04 12:36:46 -08:00
File . WriteAllText ( projectPath , GenerateProjectJsonContents ( new [ ] { "dnxcore50" } ) ) ;
Dnx . RunPackageInstall ( tooldep , projectPath , args ) ;
2015-12-18 16:39:43 -08:00
Dnx . RunRestore ( new [ ] { $"\" { projectPath } \ "" , "--runtime" , $"{DefaultRid}" } . Concat ( args ) ) ;
2016-01-04 12:36:46 -08:00
}
private static string GenerateProjectJsonContents ( IEnumerable < string > frameworks = null )
{
var sb = new StringBuilder ( ) ;
sb . AppendLine ( "{" ) ;
if ( frameworks ! = null )
{
sb . AppendLine ( " \"frameworks\":{" ) ;
foreach ( var framework in frameworks )
{
sb . AppendLine ( $" \" { framework } \ ":{{}}" ) ;
}
sb . AppendLine ( " }" ) ;
}
sb . AppendLine ( "}" ) ;
var pjContents = sb . ToString ( ) ;
return pjContents ;
}
}
}