dotnet-installer/src/dotnet/commands/dotnet-run/RunCommand.cs
Livar Cunha 3231295acf Fixing a bug in the restore option where specifying verbosity through /v was not entirely honored.
Adding tests for implicit restore for all the affected commands.

Fixing an issue where the command target was being passed to the restore command during implicit restore.

Adding restore params to all commands with implicit restore. Also, implicitly set the restore output to quiet.

Adding tests for the no-restore option.
2017-06-07 17:41:30 -07:00

260 lines
9.3 KiB
C#

// 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 Microsoft.Build.Evaluation;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Tools;
using Microsoft.DotNet.Tools.MSBuild;
using Microsoft.DotNet.Tools.Run.LaunchSettings;
namespace Microsoft.DotNet.Tools.Run
{
public partial class RunCommand
{
public string Configuration { get; private set; }
public string Framework { get; private set; }
public bool NoBuild { get; private set; }
public string Project { get; private set; }
public IReadOnlyCollection<string> Args { get; private set; }
public bool NoRestore { get; private set; }
public IEnumerable<string> RestoreArgs { get; private set; }
private List<string> _args;
private bool ShouldBuild => !NoBuild;
public string LaunchProfile { get; private set; }
public bool NoLaunchProfile { get; private set; }
private bool UseLaunchProfile => !NoLaunchProfile;
public int Start()
{
Initialize();
if (ShouldBuild)
{
EnsureProjectIsBuilt();
}
ICommand runCommand = GetRunCommand();
int launchSettingsApplicationResult = ApplyLaunchProfileSettingsIfNeeded(ref runCommand);
if (launchSettingsApplicationResult != 0)
{
return launchSettingsApplicationResult;
}
return runCommand
.Execute()
.ExitCode;
}
public RunCommand(string configuration,
string framework,
bool noBuild,
string project,
string launchProfile,
bool noLaunchProfile,
bool noRestore,
IEnumerable<string> restoreArgs,
IReadOnlyCollection<string> args)
{
Configuration = configuration;
Framework = framework;
NoBuild = noBuild;
Project = project;
LaunchProfile = launchProfile;
NoLaunchProfile = noLaunchProfile;
Args = args;
RestoreArgs = restoreArgs;
NoRestore = noRestore;
}
public RunCommand MakeNewWithReplaced(string configuration = null,
string framework = null,
bool? noBuild = null,
string project = null,
string launchProfile = null,
bool? noLaunchProfile = null,
bool? noRestore = null,
IEnumerable<string> restoreArgs = null,
IReadOnlyCollection<string> args = null)
{
return new RunCommand(
configuration ?? this.Configuration,
framework ?? this.Framework,
noBuild ?? this.NoBuild,
project ?? this.Project,
launchProfile ?? this.LaunchProfile,
noLaunchProfile ?? this.NoLaunchProfile,
noRestore ?? this.NoRestore,
restoreArgs ?? this.RestoreArgs,
args ?? this.Args
);
}
private int ApplyLaunchProfileSettingsIfNeeded(ref ICommand runCommand)
{
if (UseLaunchProfile)
{
var buildPathContainer = File.Exists(Project) ? Path.GetDirectoryName(Project) : Project;
var launchSettingsPath = Path.Combine(buildPathContainer, "Properties", "launchSettings.json");
if (File.Exists(launchSettingsPath))
{
Reporter.Output.WriteLine(string.Format(LocalizableStrings.UsingLaunchSettingsFromMessage, launchSettingsPath));
string profileName = string.IsNullOrEmpty(LaunchProfile) ? LocalizableStrings.DefaultLaunchProfileDisplayName : LaunchProfile;
try
{
var launchSettingsFileContents = File.ReadAllText(launchSettingsPath);
var applyResult = LaunchSettingsManager.TryApplyLaunchSettings(launchSettingsFileContents, ref runCommand, LaunchProfile);
if (!applyResult.Success)
{
//Error that the launch profile couldn't be applied
Reporter.Error.WriteLine(string.Format(LocalizableStrings.RunCommandExceptionCouldNotApplyLaunchSettings, profileName, applyResult.FailureReason).Bold().Red());
}
}
catch (IOException ex)
{
Reporter.Error.WriteLine(string.Format(LocalizableStrings.RunCommandExceptionCouldNotApplyLaunchSettings, profileName).Bold().Red());
Reporter.Error.WriteLine(ex.Message.Bold().Red());
return -1;
}
}
else if (!string.IsNullOrEmpty(LaunchProfile))
{
//Error that the launch profile couldn't be found
Reporter.Error.WriteLine(LocalizableStrings.RunCommandExceptionCouldNotLocateALaunchSettingsFile.Bold().Red());
}
}
return 0;
}
private void EnsureProjectIsBuilt()
{
List<string> buildArgs = new List<string>();
buildArgs.Add(Project);
buildArgs.Add("/nologo");
buildArgs.Add("/verbosity:quiet");
buildArgs.AddRange(RestoreArgs);
var buildResult = new RestoringCommand(buildArgs, NoRestore).Execute();
if (buildResult != 0)
{
Reporter.Error.WriteLine();
throw new GracefulException(LocalizableStrings.RunCommandException);
}
}
private ICommand GetRunCommand()
{
var globalProperties = new Dictionary<string, string>
{
{ Constants.MSBuildExtensionsPath, AppContext.BaseDirectory }
};
if (!string.IsNullOrWhiteSpace(Configuration))
{
globalProperties.Add("Configuration", Configuration);
}
if (!string.IsNullOrWhiteSpace(Framework))
{
globalProperties.Add("TargetFramework", Framework);
}
Project project = new Project(Project, globalProperties, null);
string runProgram = project.GetPropertyValue("RunCommand");
if (string.IsNullOrEmpty(runProgram))
{
ThrowUnableToRunError(project);
}
string runArguments = project.GetPropertyValue("RunArguments");
string runWorkingDirectory = project.GetPropertyValue("RunWorkingDirectory");
string fullArguments = runArguments;
if (_args.Any())
{
fullArguments += " " + ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(_args);
}
CommandSpec commandSpec = new CommandSpec(runProgram, fullArguments, CommandResolutionStrategy.None);
return Command.Create(commandSpec)
.WorkingDirectory(runWorkingDirectory);
}
private void ThrowUnableToRunError(Project project)
{
string targetFrameworks = project.GetPropertyValue("TargetFrameworks");
if (!string.IsNullOrEmpty(targetFrameworks))
{
string targetFramework = project.GetPropertyValue("TargetFramework");
if (string.IsNullOrEmpty(targetFramework))
{
var framework = "--framework";
throw new GracefulException(LocalizableStrings.RunCommandExceptionUnableToRunSpecifyFramework, framework);
}
}
string outputType = project.GetPropertyValue("OutputType");
throw new GracefulException(
string.Format(
LocalizableStrings.RunCommandExceptionUnableToRun,
"dotnet run",
"OutputType",
outputType));
}
private void Initialize()
{
if (string.IsNullOrWhiteSpace(Project))
{
Project = Directory.GetCurrentDirectory();
}
if (Directory.Exists(Project))
{
Project = FindSingleProjectInDirectory(Project);
}
if (Args == null)
{
_args = new List<string>();
}
else
{
_args = new List<string>(Args);
}
}
private static string FindSingleProjectInDirectory(string directory)
{
string[] projectFiles = Directory.GetFiles(directory, "*.*proj");
if (projectFiles.Length == 0)
{
var project = "--project";
throw new GracefulException(LocalizableStrings.RunCommandExceptionNoProjects, directory, project);
}
else if (projectFiles.Length > 1)
{
throw new GracefulException(LocalizableStrings.RunCommandExceptionMultipleProjects, directory);
}
return projectFiles[0];
}
}
}