Merge pull request #713 from piotrpMSFT/piotrpMSFT/Issue694/DotnetRestore

dotnet-restore
This commit is contained in:
Piotr Puszkiewicz 2016-01-06 02:27:51 -08:00
commit ab6e9577aa
17 changed files with 339 additions and 9 deletions

View file

@ -58,6 +58,7 @@ EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.DotNet.Tools.New", "src\Microsoft.DotNet.Tools.New\Microsoft.DotNet.Tools.New.xproj", "{BC765FBF-AD7A-4A99-9902-5540C5A74181}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{0722D325-24C8-4E83-B5AF-0A083E7F0749}"
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "dotnet-restore", "src\dotnet-restore\dotnet-restore.xproj", "{79620410-4EC7-4A38-A8C3-EE81243F818E}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "MultiProjectValidator", "tools\MultiProjectValidator\MultiProjectValidator.xproj", "{08A68C6A-86F6-4ED2-89A7-B166D33E9F85}"
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.DotNet.ProjectModel.Server", "src\Microsoft.DotNet.ProjectModel.Server\Microsoft.DotNet.ProjectModel.Server.xproj", "{1EA9AF94-5494-40DD-A05B-9D564572CCFC}"
@ -498,6 +499,22 @@ Global
{74F25188-BF63-4BF3-879B-B6CDB11ED608}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU
{74F25188-BF63-4BF3-879B-B6CDB11ED608}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU
{74F25188-BF63-4BF3-879B-B6CDB11ED608}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
{79620410-4EC7-4A38-A8C3-EE81243F818E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{79620410-4EC7-4A38-A8C3-EE81243F818E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{79620410-4EC7-4A38-A8C3-EE81243F818E}.Debug|x64.ActiveCfg = Debug|Any CPU
{79620410-4EC7-4A38-A8C3-EE81243F818E}.Debug|x64.Build.0 = Debug|Any CPU
{79620410-4EC7-4A38-A8C3-EE81243F818E}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU
{79620410-4EC7-4A38-A8C3-EE81243F818E}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU
{79620410-4EC7-4A38-A8C3-EE81243F818E}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
{79620410-4EC7-4A38-A8C3-EE81243F818E}.MinSizeRel|x64.Build.0 = Debug|Any CPU
{79620410-4EC7-4A38-A8C3-EE81243F818E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{79620410-4EC7-4A38-A8C3-EE81243F818E}.Release|Any CPU.Build.0 = Release|Any CPU
{79620410-4EC7-4A38-A8C3-EE81243F818E}.Release|x64.ActiveCfg = Release|Any CPU
{79620410-4EC7-4A38-A8C3-EE81243F818E}.Release|x64.Build.0 = Release|Any CPU
{79620410-4EC7-4A38-A8C3-EE81243F818E}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU
{79620410-4EC7-4A38-A8C3-EE81243F818E}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU
{79620410-4EC7-4A38-A8C3-EE81243F818E}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU
{79620410-4EC7-4A38-A8C3-EE81243F818E}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
{1EA9AF94-5494-40DD-A05B-9D564572CCFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1EA9AF94-5494-40DD-A05B-9D564572CCFC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1EA9AF94-5494-40DD-A05B-9D564572CCFC}.Debug|x64.ActiveCfg = Debug|Any CPU
@ -561,6 +578,7 @@ Global
{0A309227-A9D8-4DDF-88DD-326B57B04379} = {ED2FE3E2-F7E7-4389-8231-B65123F2076F}
{688870C8-9843-4F9E-8576-D39290AD0F25} = {ED2FE3E2-F7E7-4389-8231-B65123F2076F}
{74F25188-BF63-4BF3-879B-B6CDB11ED608} = {ED2FE3E2-F7E7-4389-8231-B65123F2076F}
{79620410-4EC7-4A38-A8C3-EE81243F818E} = {ED2FE3E2-F7E7-4389-8231-B65123F2076F}
{1EA9AF94-5494-40DD-A05B-9D564572CCFC} = {ED2FE3E2-F7E7-4389-8231-B65123F2076F}
{11C77123-E4DA-499F-8900-80C88C2C69F2} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7}
EndGlobalSection

View file

@ -11,4 +11,7 @@ $env:PATH = "$env:DOTNET_INSTALL_DIR\cli\bin;$StartPath"
_ "$RepoRoot\scripts\compile\compile-stage.ps1" @("$Tfm","$Rid","$Configuration","$Stage1Dir","$RepoRoot","$HostDir")
# Copy dnx into stage 1
cp -rec "$DnxRoot\" "$Stage1Dir\bin\dnx\"
$env:PATH=$StartPath

View file

@ -23,4 +23,11 @@ export PATH=$DOTNET_INSTALL_DIR/bin:$PATH
header "Building stage1 dotnet using downloaded stage0 ..."
OUTPUT_DIR=$STAGE1_DIR $REPOROOT/scripts/compile/compile-stage.sh
# Copy DNX in to stage1
cp -R $DNX_ROOT $STAGE1_DIR/bin/dnx
# Copy and CHMOD the dotnet-dnx script
cp $REPOROOT/scripts/dotnet-dnx.sh $STAGE1_DIR/bin/dotnet-dnx
chmod a+x $STAGE1_DIR/bin/dotnet-dnx
export PATH=$StartPath

View file

@ -22,6 +22,7 @@ $Projects = @(
"Microsoft.DotNet.Tools.New",
"Microsoft.DotNet.Tools.Pack",
"Microsoft.DotNet.Tools.Publish",
"dotnet-restore",
"Microsoft.DotNet.Tools.Repl",
"Microsoft.DotNet.Tools.Repl.Csi",
"Microsoft.DotNet.Tools.Resgen",
@ -92,8 +93,8 @@ _cmd "$RepoRoot\scripts\crossgen\crossgen_roslyn.cmd ""$OutputDir"""
# Copy dnx into stage OutputDir
cp -rec "$DnxRoot\" "$OutputDir\bin\dnx\"
# Copy in the dotnet-restore script
cp "$RepoRoot\scripts\dotnet-restore.cmd" "$OutputDir\bin\dotnet-restore.cmd"
# Copy in the dotnet-dnx script
cp "$RepoRoot\scripts\dotnet-dnx.cmd" "$OutputDir\bin\dotnet-dnx.cmd"
# Copy in AppDeps
$env:PATH = "$OutputDir\bin;$StartPath"

View file

@ -35,6 +35,7 @@ PROJECTS=( \
Microsoft.DotNet.Tools.Publish \
Microsoft.DotNet.Tools.Repl \
Microsoft.DotNet.Tools.Repl.Csi \
dotnet-restore \
Microsoft.DotNet.Tools.Resgen \
Microsoft.DotNet.Tools.Run \
Microsoft.DotNet.Tools.Test \
@ -102,9 +103,9 @@ chmod -R a+r $OUTPUT_DIR
# Copy DNX in to OUTPUT_DIR
cp -R $DNX_ROOT $OUTPUT_DIR/bin/dnx
# Copy and CHMOD the dotnet-restore script
cp $REPOROOT/scripts/dotnet-restore.sh $OUTPUT_DIR/bin/dotnet-restore
chmod a+x $OUTPUT_DIR/bin/dotnet-restore
# Copy and CHMOD the dotnet-dnx script
cp $REPOROOT/scripts/dotnet-dnx.sh $OUTPUT_DIR/bin/dotnet-dnx
chmod a+x $OUTPUT_DIR/bin/dotnet-dnx
# No compile native support in centos yet
# https://github.com/dotnet/cli/issues/453

View file

@ -6,7 +6,7 @@ REM Licensed under the MIT license. See LICENSE file in the project root for ful
SETLOCAL
SET ERRORLEVEL=
"%~dp0dnx\dnx" "%~dp0dnx\lib\Microsoft.Dnx.Tooling\Microsoft.Dnx.Tooling.dll" restore %*
"%~dp0dnx\dnx" "%~dp0dnx\lib\Microsoft.Dnx.Tooling\Microsoft.Dnx.Tooling.dll" %*
exit /b %ERRORLEVEL%
ENDLOCAL

View file

@ -17,4 +17,4 @@ DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
# work around restore timeouts on Mono
[ -z "$MONO_THREADS_PER_CPU" ] && export MONO_THREADS_PER_CPU=50
exec "$DIR/dnx/dnx" "$DIR/dnx/lib/Microsoft.Dnx.Tooling/Microsoft.Dnx.Tooling.dll" "restore" "$@"
exec "$DIR/dnx/dnx" "$DIR/dnx/lib/Microsoft.Dnx.Tooling/Microsoft.Dnx.Tooling.dll" "$@"

View file

@ -13,7 +13,7 @@ using NuGet.Versioning;
namespace Microsoft.DotNet.ProjectModel.Graph
{
internal static class LockFileReader
public static class LockFileReader
{
public static LockFile Read(string filePath)
{

View file

@ -62,6 +62,8 @@ namespace Microsoft.DotNet.ProjectModel
public IList<LibraryRange> Dependencies { get; set; }
public List<LibraryRange> Tools { get; set; }
public string EntryPoint { get; set; }
public string ProjectUrl { get; set; }

View file

@ -1,7 +1,6 @@
// 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;

View file

@ -69,6 +69,7 @@ namespace Microsoft.DotNet.ProjectModel
public static Project GetProject(string projectFile, ICollection<DiagnosticMessage> diagnostics, ProjectReaderSettings settings = null)
{
var name = Path.GetFileName(Path.GetDirectoryName(projectFile));
using (var stream = new FileStream(projectFile, FileMode.Open, FileAccess.Read, FileShare.Read))
{
return new ProjectReader().ReadProject(stream, name, projectFile, diagnostics, settings);
@ -156,6 +157,7 @@ namespace Microsoft.DotNet.ProjectModel
project.EmbedInteropTypes = rawProject.ValueAsBoolean("embedInteropTypes", defaultValue: false);
project.Dependencies = new List<LibraryRange>();
project.Tools = new List<LibraryRange>();
// Project files
project.Files = new ProjectFilesCollection(rawProject, project.ProjectDirectory, project.ProjectFilePath);
@ -208,6 +210,13 @@ namespace Microsoft.DotNet.ProjectModel
"dependencies",
isGacOrFrameworkReference: false);
PopulateDependencies(
project.ProjectFilePath,
project.Tools,
rawProject,
"tools",
isGacOrFrameworkReference: false);
return project;
}

35
src/dotnet-restore/Dnx.cs Normal file
View file

@ -0,0 +1,35 @@
using System.Collections.Generic;
using System.Linq;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.ProjectModel.Graph;
namespace Microsoft.DotNet.Tools.Restore
{
public static class Dnx
{
public static int RunRestore(IEnumerable<string> args)
{
var result = RunDnx(new List<string> {"restore"}.Concat(args))
.ForwardStdErr()
.ForwardStdOut()
.Execute();
return result.ExitCode;
}
public static int RunPackageInstall(LibraryRange dependency, string projectPath, IEnumerable<string> args)
{
var result = RunDnx(new List<string> { "install", dependency.Name, dependency.VersionRange.OriginalString, projectPath }.Concat(args))
.ForwardStdErr()
.ForwardStdOut()
.Execute();
return result.ExitCode;
}
private static Command RunDnx(IEnumerable<string> dnxArgs)
{
return Command.Create("dotnet-dnx", dnxArgs);
}
}
}

View file

@ -0,0 +1,179 @@
// 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;
namespace Microsoft.DotNet.Tools.Restore
{
public class Program
{
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);
RestoreTools(project, restoreTask.Arguments);
}
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);
}
private static void RestoreTools(Project project, IEnumerable<string> args)
{
foreach (var tooldep in project.Tools)
{
RestoreTool(tooldep, args);
}
}
private static void RestoreTool(LibraryRange tooldep, IEnumerable<string> args)
{
var tempPath = Path.Combine(Directory.GetCurrentDirectory(), Guid.NewGuid().ToString(), "bin");
RestoreToolToPath(tooldep, args, tempPath);
CreateDepsInPackageCache(tooldep, tempPath);
PersistLockFile(tooldep, tempPath);
Directory.Delete(tempPath, true);
}
private static void PersistLockFile(LibraryRange tooldep, string tempPath)
{
var targetPath = Path.Combine(Directory.GetCurrentDirectory(), "artifacts", "Tools", tooldep.Name);
if (Directory.Exists(targetPath)) Directory.Delete(targetPath, true);
Directory.CreateDirectory(targetPath);
File.Move(Path.Combine(tempPath, "project.lock.json"), Path.Combine(targetPath, "project.lock.json"));
}
private static void CreateDepsInPackageCache(LibraryRange toolLibrary, string projectPath)
{
var context = ProjectContext.Create(projectPath,
FrameworkConstants.CommonFrameworks.DnxCore50, new[] { RuntimeIdentifier.Current });
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);
File.WriteAllText(projectPath, GenerateProjectJsonContents(new[] {"dnxcore50"}));
Dnx.RunPackageInstall(tooldep, projectPath, args);
Dnx.RunRestore(new [] { $"\"{projectPath}\"", "--runtime", $"{RuntimeIdentifier.Current}"}.Concat(args));
}
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;
}
}
}

View file

@ -0,0 +1,8 @@
// 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.Reflection;
using System.Resources;
[assembly: AssemblyMetadata("Serviceable", "True")]
[assembly: NeutralResourcesLanguage("en-us")]

View file

@ -0,0 +1,11 @@
using System.Collections.Generic;
namespace Microsoft.DotNet.Tools.Restore
{
public struct RestoreTask
{
public string ProjectPath { get; set; }
public IEnumerable<string> Arguments { get; set; }
}
}

View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>79620410-4ec7-4a38-a8c3-ee81243f818e</ProjectGuid>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View file

@ -0,0 +1,40 @@
{
"name": "dotnet-restore",
"description": "Restore packages specified in project.json (project file)",
"version": "1.0.0-*",
"repository": {
"type": "git",
"url": "git://github.com/dotnet/cli"
},
"compilationOptions": {
"warningsAsErrors": true,
"emitEntryPoint": true
},
"dependencies": {
"Microsoft.NETCore.ConsoleHost": "1.0.0-beta-23409",
"NETStandard.Library": "1.0.0-rc2-23608",
"System.Linq": "4.0.1-beta-23504",
"System.Collections": "4.0.11-beta-23504",
"Microsoft.DotNet.Cli.Utils": "1.0.0-*",
"Microsoft.DotNet.Compiler.Common": "1.0.0-*",
"Microsoft.Dnx.Runtime.CommandParsing.Sources": {
"version": "1.0.0-*",
"type": "build"
},
"Microsoft.Extensions.CommandLineUtils.Sources": {
"version": "1.0.0-*",
"type": "build"
},
"Microsoft.Extensions.Logging": "1.0.0-*",
"Newtonsoft.Json": "7.0.1"
},
"frameworks": {
"dnxcore50": {}
},
"scripts": {
"postcompile": [
"../../scripts/build/place-binary \"%compile:OutputDir%/%project:Name%.dll\"",
"../../scripts/build/place-binary \"%compile:OutputDir%/%project:Name%.pdb\""
]
}
}