From 86296b6d2d83d4e6fef6c0d470a4b2aa6ca08853 Mon Sep 17 00:00:00 2001 From: Sridhar Periyasamy Date: Sun, 29 Nov 2015 00:14:30 -0800 Subject: [PATCH] dotnet-publish '--framework' and '--runtime' options are made to be optional. When no 'runtime' and 'framework' are specified then publish for all 'framework/runtime' targets found in project.lock.json. But currently when 'runtime' is not specified then current OS runtime identifier is assumed. This will go away when xplat publish is enabled. Example - 'dotnet publish /home/sridhar/foo/project.json' -> Publish for all targets in project.lock.json. User can also specify either 'framework' or 'runtime'. In that case all the corresponding 'framework' or 'runtime' targets in project.lock.json are published. Example - 'dotnet publish --framework dnxcore50 /home/sridhar/foo/project.json' -> Publish for all targets in project.lock.json with framework dnxcore50. (or) 'dotnet publish --runtime win7-x64 /home/sridhar/foo/project.json' -> Publish for all targets in project.lock.json with runtime win7-x64. I am also adding unit tests for publish in upcoming commits. Fixes - #185 --- .../Graph/LockFileReader.cs | 2 +- src/Microsoft.DotNet.Tools.Publish/Program.cs | 84 ++++++++++++++++--- 2 files changed, 75 insertions(+), 11 deletions(-) diff --git a/src/Microsoft.DotNet.ProjectModel/Graph/LockFileReader.cs b/src/Microsoft.DotNet.ProjectModel/Graph/LockFileReader.cs index 1d76a320a..8e432d9c1 100644 --- a/src/Microsoft.DotNet.ProjectModel/Graph/LockFileReader.cs +++ b/src/Microsoft.DotNet.ProjectModel/Graph/LockFileReader.cs @@ -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) { diff --git a/src/Microsoft.DotNet.Tools.Publish/Program.cs b/src/Microsoft.DotNet.Tools.Publish/Program.cs index 62a99ccbe..977871afd 100644 --- a/src/Microsoft.DotNet.Tools.Publish/Program.cs +++ b/src/Microsoft.DotNet.Tools.Publish/Program.cs @@ -8,6 +8,7 @@ using Microsoft.Dnx.Runtime.Common.CommandLine; using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.ProjectModel; using Microsoft.DotNet.ProjectModel.Compilation; +using Microsoft.DotNet.ProjectModel.Graph; using NuGet.Frameworks; namespace Microsoft.DotNet.Tools.Publish @@ -32,13 +33,16 @@ namespace Microsoft.DotNet.Tools.Publish app.OnExecute(() => { - if (!CheckArg(framework)) + if (framework.HasValue() && IsUnsupportedFramework(framework.Value())) { + Reporter.Output.WriteLine($"Unsupported framework {framework.Value()}.".Red()); return 1; } - if (!CheckArg(runtime)) + + // TODO: Remove this once xplat publish is enabled. + if (!runtime.HasValue()) { - return 1; + runtime.Values.Add(RuntimeIdentifier.Current); } // Locate the project and get the name and full path @@ -48,18 +52,58 @@ namespace Microsoft.DotNet.Tools.Publish path = Directory.GetCurrentDirectory(); } - // Load project context and publish it - var fx = NuGetFramework.Parse(framework.Value()); - var rids = new[] { runtime.Value() }; - var context = ProjectContext.Create(path, fx, rids); + // get the lock file + var projectDir = path.ToLower().EndsWith(Project.FileName) ? + Path.GetDirectoryName(path) : + path; - if (string.IsNullOrEmpty(context.RuntimeIdentifier)) + var projectLockJsonPath = Path.Combine(projectDir, LockFile.FileName); + if (!File.Exists(projectLockJsonPath)) { - Reporter.Output.WriteLine($"Unknown runtime identifier {runtime.Value()}.".Red()); + Reporter.Output.WriteLine($"Unable to locate {LockFile.FileName} for project '{project.Value}'".Red()); + Reporter.Output.WriteLine($"Run 'dotnet restore' before calling 'dotnet publish'".Red()); return 1; } - return Publish(context, output.Value(), configuration.Value() ?? Constants.DefaultConfiguration); + var lockFile = LockFileReader.Read(projectLockJsonPath); + + var lockFileTargets = lockFile.Targets.Where(target => + { + if(target.TargetFramework == null || string.IsNullOrEmpty(target.RuntimeIdentifier)) + { + return false; + } + + if (!runtime.HasValue() || runtime.Value().Equals(target.RuntimeIdentifier)) + { + if (!framework.HasValue() || NuGetFramework.Parse(framework.Value()).Equals(target.TargetFramework)) + { + return true; + } + } + + return false; + }); + + if(lockFileTargets.Count() == 0) + { + string errMsg = $"'{project.Value}' cannot be published"; + if(framework.HasValue() || runtime.HasValue()) + { + errMsg += $" for '{framework.Value()}' '{runtime.Value()}'"; + } + + Reporter.Output.WriteLine(errMsg.Red()); + return 1; + } + + int result = 0; + foreach(var target in lockFileTargets) + { + result += Publish(target.TargetFramework, target.RuntimeIdentifier, path, output.Value(), configuration.Value() ?? Constants.DefaultConfiguration); + } + + return result; }); try @@ -87,6 +131,26 @@ namespace Microsoft.DotNet.Tools.Publish return true; } + private static bool IsUnsupportedFramework(string framework) + { + return NuGetFramework.Parse(framework).Equals(NuGetFramework.UnsupportedFramework); + } + + private static int Publish(NuGetFramework framework, string runtimeIdentifier, string projectPath, string outputPath, string configuration) + { + // Load project context and publish it + var rids = new[] { runtimeIdentifier }; + var context = ProjectContext.Create(projectPath, framework, rids); + + if (string.IsNullOrEmpty(context.RuntimeIdentifier)) + { + Reporter.Output.WriteLine($"{context.RootProject.Identity} cannot be published for {context.TargetFramework.DotNetFrameworkName}/{runtimeIdentifier}.".Red()); + return 1; + } + + return Publish(context, outputPath, configuration); + } + private static int Publish(ProjectContext context, string outputPath, string configuration) { Reporter.Output.WriteLine($"Publishing {context.RootProject.Identity.Name.Yellow()} for {context.TargetFramework.DotNetFrameworkName.Yellow()}/{context.RuntimeIdentifier.Yellow()}");