Merge pull request #5057 from dotnet/dev/jgoshi/removeProj

Implement dotnet remove project
This commit is contained in:
Livar 2016-12-16 18:56:28 -08:00 committed by GitHub
commit 9c3141b63f
33 changed files with 1141 additions and 541 deletions

View file

@ -16,7 +16,7 @@
<ItemGroup>
<Compile Include="**\*.cs" Exclude="bin\**;obj\**;**\*.xproj;packages\**" />
<Compile Include="..\..\..\src\dotnet\CommandLine\*.cs" Exclude="bin\**;obj\**;**\*.xproj;packages\**" />
<Compile Include="..\..\..\src\dotnet\CommandLine\*.cs;..\..\..\src\dotnet\CommonLocalizableStrings.cs;" Exclude="bin\**;obj\**;**\*.xproj;packages\**" />
<EmbeddedResource Include="**\*.resx" />
<EmbeddedResource Include="compiler\resources\**\*" />
</ItemGroup>

View file

@ -0,0 +1,38 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26006.2
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "App", "App\App.csproj", "{7072A694-548F-4CAE-A58F-12D257D5F486}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lib", "Lib\Lib.csproj", "{B38B1FA5-B4C9-456A-8B71-8FCD62ACF400}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lib", "Lib\Lib.csproj", "{B38B1FA5-B4C9-456A-8B71-8FCD62ACF400}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x64.ActiveCfg = Debug|x64
{7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x64.Build.0 = Debug|x64
{7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x86.ActiveCfg = Debug|x86
{7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x86.Build.0 = Debug|x86
{7072A694-548F-4CAE-A58F-12D257D5F486}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7072A694-548F-4CAE-A58F-12D257D5F486}.Release|Any CPU.Build.0 = Release|Any CPU
{7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x64.ActiveCfg = Release|x64
{7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x64.Build.0 = Release|x64
{7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x86.ActiveCfg = Release|x86
{7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View file

@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp1.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include="**\*.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Lib\Lib.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NETCore.App" Version="1.0.1" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,10 @@
using System;
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello from the main app");
Console.WriteLine(Lib.Library.GetMessage());
}
}

View file

@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
<PropertyGroup>
<TargetFramework>netstandard1.4</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include="**\*.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="NETStandard.Library" Version="1.6" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,12 @@
using System;
namespace Lib
{
public class Library
{
public static string GetMessage()
{
return "Message from Lib";
}
}
}

View file

@ -56,15 +56,34 @@ namespace Microsoft.DotNet.Cli.CommandLine
public bool HandleRemainingArguments { get; set; }
public string ArgumentSeparatorHelpText { get; set; }
public CommandLineApplication Command(string name, bool throwOnUnexpectedArg = true)
public CommandLineApplication AddCommand(string name, bool throwOnUnexpectedArg = true)
{
return Command(name, _ => { }, throwOnUnexpectedArg);
return AddCommand(name, _ => { }, throwOnUnexpectedArg);
}
public CommandLineApplication Command(string name, Action<CommandLineApplication> configuration,
public CommandLineApplication AddCommand(string name, Action<CommandLineApplication> configuration,
bool throwOnUnexpectedArg = true)
{
var command = new CommandLineApplication(throwOnUnexpectedArg) { Name = name, Parent = this };
var command = new CommandLineApplication(throwOnUnexpectedArg) { Name = name };
return AddCommand(command, configuration, throwOnUnexpectedArg);
}
public CommandLineApplication AddCommand(CommandLineApplication command, bool throwOnUnexpectedArg = true)
{
return AddCommand(command, _ => { }, throwOnUnexpectedArg);
}
public CommandLineApplication AddCommand(
CommandLineApplication command,
Action<CommandLineApplication> configuration,
bool throwOnUnexpectedArg = true)
{
if (command == null || configuration == null)
{
throw new NullReferenceException();
}
command.Parent = this;
Commands.Add(command);
configuration(command);
return command;

View file

@ -2,11 +2,14 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using Microsoft.DotNet.Tools;
namespace Microsoft.DotNet.Cli.CommandLine
{
internal class CommandParsingException : Exception
{
private bool _isRequireSubCommandMissing;
public CommandParsingException(
CommandLineApplication command,
string message,
@ -14,10 +17,19 @@ namespace Microsoft.DotNet.Cli.CommandLine
: base(message)
{
Command = command;
IsRequireSubCommandMissing = isRequireSubCommandMissing;
_isRequireSubCommandMissing = isRequireSubCommandMissing;
}
public CommandLineApplication Command { get; }
public bool IsRequireSubCommandMissing { get; }
public override string Message
{
get
{
return _isRequireSubCommandMissing
? CommonLocalizableStrings.RequiredCommandNotPassed
: base.Message;
}
}
}
}

View file

@ -0,0 +1,16 @@
// 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 Microsoft.DotNet.Cli.CommandLine;
namespace Microsoft.DotNet.Cli
{
internal abstract class DotNetSubCommandBase : CommandLineApplication
{
internal DotNetSubCommandBase() : base(throwOnUnexpectedArg: false)
{
}
public abstract int Run(string fileOrDirectory);
}
}

View file

@ -3,10 +3,12 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.DotNet.Cli.CommandLine;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Tools;
using Microsoft.DotNet.Tools.Add.ProjectToProjectReference;
using Microsoft.DotNet.Tools.Common;
namespace Microsoft.DotNet.Cli
{
@ -14,46 +16,67 @@ namespace Microsoft.DotNet.Cli
{
protected abstract string CommandName { get; }
protected abstract string FullCommandNameLocalized { get; }
internal abstract List<Func<CommandLineApplication, CommandLineApplication>> SubCommands { get; }
internal abstract List<Func<DotNetSubCommandBase>> SubCommands { get; }
public int RunCommand(string[] args)
{
DebugHelper.HandleDebugSwitch(ref args);
CommandLineApplication app = new CommandLineApplication(throwOnUnexpectedArg: true)
CommandLineApplication command = new CommandLineApplication(throwOnUnexpectedArg: true)
{
Name = $"dotnet {CommandName}",
FullName = FullCommandNameLocalized,
};
app.HelpOption("-h|--help");
command.HelpOption("-h|--help");
app.Argument(
command.Argument(
Constants.ProjectOrSolutionArgumentName,
CommonLocalizableStrings.ArgumentsProjectOrSolutionDescription);
foreach (var subCommandCreator in SubCommands)
{
subCommandCreator(app);
var subCommand = subCommandCreator();
command.AddCommand(subCommand);
subCommand.OnExecute(() => {
try
{
if (!command.Arguments.Any())
{
throw new GracefulException(CommonLocalizableStrings.RequiredArgumentNotPassed, Constants.ProjectOrSolutionArgumentName);
}
var projectOrDirectory = command.Arguments.First().Value;
if (string.IsNullOrEmpty(projectOrDirectory))
{
projectOrDirectory = PathUtility.EnsureTrailingSlash(Directory.GetCurrentDirectory());
}
return subCommand.Run(projectOrDirectory);
}
catch (GracefulException e)
{
Reporter.Error.WriteLine(e.Message.Red());
subCommand.ShowHelp();
return 1;
}
});
}
try
{
return app.Execute(args);
return command.Execute(args);
}
catch (GracefulException e)
{
Reporter.Error.WriteLine(e.Message.Red());
app.ShowHelp();
command.ShowHelp();
return 1;
}
catch (CommandParsingException e)
{
string errorMessage = e.IsRequireSubCommandMissing
? CommonLocalizableStrings.RequiredCommandNotPassed
: e.Message;
Reporter.Error.WriteLine(errorMessage.Red());
Reporter.Error.WriteLine(e.Message.Red());
return 1;
}
}

View file

@ -4,7 +4,6 @@
using System;
using System.Collections.Generic;
using Microsoft.DotNet.Cli;
using Microsoft.DotNet.Cli.CommandLine;
using Microsoft.DotNet.Tools.Add.ProjectToProjectReference;
using Microsoft.DotNet.Tools.Add.ProjectToSolution;
@ -14,11 +13,11 @@ namespace Microsoft.DotNet.Tools.Add
{
protected override string CommandName => "add";
protected override string FullCommandNameLocalized => LocalizableStrings.NetAddCommand;
internal override List<Func<CommandLineApplication, CommandLineApplication>> SubCommands =>
new List<Func<CommandLineApplication, CommandLineApplication>>
internal override List<Func<DotNetSubCommandBase>> SubCommands =>
new List<Func<DotNetSubCommandBase>>
{
AddProjectToSolutionCommand.CreateApplication,
AddProjectToProjectReferenceCommand.CreateApplication,
AddProjectToSolutionCommand.Create,
AddProjectToProjectReferenceCommand.Create,
};
public static int Run(string[] args)

View file

@ -2,6 +2,7 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using Microsoft.Build.Evaluation;
using Microsoft.DotNet.Cli;
using Microsoft.DotNet.Cli.CommandLine;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Tools.Common;
@ -13,111 +14,100 @@ using System.Text;
namespace Microsoft.DotNet.Tools.Add.ProjectToProjectReference
{
public class AddProjectToProjectReferenceCommand
internal class AddProjectToProjectReferenceCommand : DotNetSubCommandBase
{
internal static CommandLineApplication CreateApplication(CommandLineApplication parentApp)
private CommandOption _frameworkOption;
public static DotNetSubCommandBase Create()
{
CommandLineApplication app = parentApp.Command("p2p", throwOnUnexpectedArg: false);
app.FullName = LocalizableStrings.AppFullName;
app.Description = LocalizableStrings.AppDescription;
app.HandleRemainingArguments = true;
app.ArgumentSeparatorHelpText = LocalizableStrings.AppHelpText;
app.HelpOption("-h|--help");
CommandOption frameworkOption = app.Option(
$"-f|--framework <{CommonLocalizableStrings.CmdFramework}>",
LocalizableStrings.CmdFrameworkDescription,
CommandOptionType.SingleValue);
app.OnExecute(() =>
var command = new AddProjectToProjectReferenceCommand()
{
try
Name = "p2p",
FullName = LocalizableStrings.AppFullName,
Description = LocalizableStrings.AppDescription,
HandleRemainingArguments = true,
ArgumentSeparatorHelpText = LocalizableStrings.AppHelpText,
};
command.HelpOption("-h|--help");
command._frameworkOption = command.Option(
$"-f|--framework <{CommonLocalizableStrings.CmdFramework}>",
LocalizableStrings.CmdFrameworkDescription,
CommandOptionType.SingleValue);
return command;
}
public override int Run(string fileOrDirectory)
{
var projects = new ProjectCollection();
MsbuildProject msbuildProj = MsbuildProject.FromFileOrDirectory(projects, fileOrDirectory);
if (RemainingArguments.Count == 0)
{
throw new GracefulException(CommonLocalizableStrings.SpecifyAtLeastOneReferenceToAdd);
}
string frameworkString = _frameworkOption.Value();
PathUtility.EnsureAllPathsExist(RemainingArguments, CommonLocalizableStrings.ReferenceDoesNotExist);
List<MsbuildProject> refs = RemainingArguments
.Select((r) => MsbuildProject.FromFile(projects, r))
.ToList();
if (frameworkString == null)
{
foreach (var tfm in msbuildProj.GetTargetFrameworks())
{
if (!parentApp.Arguments.Any())
foreach (var @ref in refs)
{
throw new GracefulException(CommonLocalizableStrings.RequiredArgumentNotPassed, Constants.ProjectOrSolutionArgumentName);
}
var projectOrDirectory = parentApp.Arguments.First().Value;
if (string.IsNullOrEmpty(projectOrDirectory))
{
projectOrDirectory = PathUtility.EnsureTrailingSlash(Directory.GetCurrentDirectory());
}
var projects = new ProjectCollection();
var msbuildProj = MsbuildProject.FromFileOrDirectory(projects, projectOrDirectory);
if (app.RemainingArguments.Count == 0)
{
throw new GracefulException(CommonLocalizableStrings.SpecifyAtLeastOneReferenceToAdd);
}
string frameworkString = frameworkOption.Value();
List<string> references = app.RemainingArguments;
PathUtility.EnsureAllPathsExist(references, CommonLocalizableStrings.ReferenceDoesNotExist);
IEnumerable<MsbuildProject> refs = references.Select((r) => MsbuildProject.FromFile(projects, r));
if (frameworkString == null)
{
foreach (var tfm in msbuildProj.GetTargetFrameworks())
if (!@ref.CanWorkOnFramework(tfm))
{
foreach (var @ref in refs)
{
if (!@ref.CanWorkOnFramework(tfm))
{
Reporter.Error.Write(GetProjectNotCompatibleWithFrameworksDisplayString(
@ref,
msbuildProj.GetTargetFrameworks().Select((fx) => fx.GetShortFolderName())));
return 1;
}
}
}
}
else
{
var framework = NuGetFramework.Parse(frameworkString);
if (!msbuildProj.IsTargettingFramework(framework))
{
Reporter.Error.WriteLine(string.Format(CommonLocalizableStrings.ProjectDoesNotTargetFramework, msbuildProj.ProjectRootElement.FullPath, frameworkString));
Reporter.Error.Write(GetProjectNotCompatibleWithFrameworksDisplayString(
@ref,
msbuildProj.GetTargetFrameworks().Select((fx) => fx.GetShortFolderName())));
return 1;
}
foreach (var @ref in refs)
{
if (!@ref.CanWorkOnFramework(framework))
{
Reporter.Error.Write(GetProjectNotCompatibleWithFrameworksDisplayString(
@ref,
new string[] { frameworkString }));
return 1;
}
}
}
var relativePathReferences = references.Select((r) =>
PathUtility.GetRelativePath(msbuildProj.ProjectDirectory, Path.GetFullPath(r))).ToList();
int numberOfAddedReferences = msbuildProj.AddProjectToProjectReferences(
frameworkOption.Value(),
relativePathReferences);
if (numberOfAddedReferences != 0)
{
msbuildProj.ProjectRootElement.Save();
}
return 0;
}
catch (GracefulException e)
}
else
{
var framework = NuGetFramework.Parse(frameworkString);
if (!msbuildProj.IsTargettingFramework(framework))
{
Reporter.Error.WriteLine(e.Message.Red());
app.ShowHelp();
Reporter.Error.WriteLine(string.Format(
CommonLocalizableStrings.ProjectDoesNotTargetFramework,
msbuildProj.ProjectRootElement.FullPath,
frameworkString));
return 1;
}
});
return app;
foreach (var @ref in refs)
{
if (!@ref.CanWorkOnFramework(framework))
{
Reporter.Error.Write(GetProjectNotCompatibleWithFrameworksDisplayString(
@ref,
new string[] { frameworkString }));
return 1;
}
}
}
var relativePathReferences = RemainingArguments.Select((r) =>
PathUtility.GetRelativePath(msbuildProj.ProjectDirectory, Path.GetFullPath(r))).ToList();
int numberOfAddedReferences = msbuildProj.AddProjectToProjectReferences(
_frameworkOption.Value(),
relativePathReferences);
if (numberOfAddedReferences != 0)
{
msbuildProj.ProjectRootElement.Save();
}
return 0;
}
private static string GetProjectNotCompatibleWithFrameworksDisplayString(MsbuildProject project, IEnumerable<string> frameworksDisplayStrings)

View file

@ -3,83 +3,64 @@
using Microsoft.Build.Construction;
using Microsoft.Build.Evaluation;
using Microsoft.DotNet.Cli.CommandLine;
using Microsoft.DotNet.Cli;
using Microsoft.DotNet.Cli.Sln.Internal;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Tools.Common;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Microsoft.DotNet.Tools.Add.ProjectToSolution
{
public class AddProjectToSolutionCommand
internal class AddProjectToSolutionCommand : DotNetSubCommandBase
{
internal static CommandLineApplication CreateApplication(CommandLineApplication parentApp)
public static DotNetSubCommandBase Create()
{
CommandLineApplication app = parentApp.Command("project", throwOnUnexpectedArg: false);
app.FullName = LocalizableStrings.AppFullName;
app.Description = LocalizableStrings.AppDescription;
app.HandleRemainingArguments = true;
app.ArgumentSeparatorHelpText = LocalizableStrings.AppHelpText;
app.HelpOption("-h|--help");
app.OnExecute(() =>
var command = new AddProjectToSolutionCommand()
{
try
{
if (!parentApp.Arguments.Any())
{
throw new GracefulException(CommonLocalizableStrings.RequiredArgumentNotPassed, Constants.ProjectOrSolutionArgumentName);
}
Name = "project",
FullName = LocalizableStrings.AppFullName,
Description = LocalizableStrings.AppDescription,
HandleRemainingArguments = true,
ArgumentSeparatorHelpText = LocalizableStrings.AppHelpText,
};
var projectOrDirectory = parentApp.Arguments.First().Value;
if (string.IsNullOrEmpty(projectOrDirectory))
{
projectOrDirectory = PathUtility.EnsureTrailingSlash(Directory.GetCurrentDirectory());
}
command.HelpOption("-h|--help");
SlnFile slnFile = SlnFileFactory.CreateFromFileOrDirectory(projectOrDirectory);
if (app.RemainingArguments.Count == 0)
{
throw new GracefulException(CommonLocalizableStrings.SpecifyAtLeastOneProjectToAdd);
}
List<string> projectPaths = app.RemainingArguments;
PathUtility.EnsureAllPathsExist(projectPaths, CommonLocalizableStrings.ProjectDoesNotExist);
var relativeProjectPaths = projectPaths.Select((p) =>
PathUtility.GetRelativePath(
PathUtility.EnsureTrailingSlash(slnFile.BaseDirectory),
Path.GetFullPath(p))).ToList();
int preAddProjectCount = slnFile.Projects.Count;
foreach (var project in relativeProjectPaths)
{
AddProject(slnFile, project);
}
if (slnFile.Projects.Count > preAddProjectCount)
{
slnFile.Write();
}
return 0;
}
catch (GracefulException e)
{
Reporter.Error.WriteLine(e.Message.Red());
app.ShowHelp();
return 1;
}
});
return app;
return command;
}
private static void AddProject(SlnFile slnFile, string projectPath)
public override int Run(string fileOrDirectory)
{
SlnFile slnFile = SlnFileFactory.CreateFromFileOrDirectory(fileOrDirectory);
if (RemainingArguments.Count == 0)
{
throw new GracefulException(CommonLocalizableStrings.SpecifyAtLeastOneProjectToAdd);
}
PathUtility.EnsureAllPathsExist(RemainingArguments, CommonLocalizableStrings.ProjectDoesNotExist);
var relativeProjectPaths = RemainingArguments.Select((p) =>
PathUtility.GetRelativePath(
PathUtility.EnsureTrailingSlash(slnFile.BaseDirectory),
Path.GetFullPath(p))).ToList();
int preAddProjectCount = slnFile.Projects.Count;
foreach (var project in relativeProjectPaths)
{
AddProject(slnFile, project);
}
if (slnFile.Projects.Count > preAddProjectCount)
{
slnFile.Write();
}
return 0;
}
private void AddProject(SlnFile slnFile, string projectPath)
{
var projectPathNormalized = PathUtility.GetPathWithBackSlashes(projectPath);

View file

@ -1,13 +0,0 @@
// 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.Collections.Generic;
namespace Microsoft.DotNet.Tools.List
{
public interface IListSubCommand
{
string LocalizedErrorMessageNoItemsFound { get; }
IList<string> Items { get; }
}
}

View file

@ -1,71 +0,0 @@
// 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 Microsoft.DotNet.Cli.CommandLine;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Tools.Common;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Microsoft.DotNet.Tools.List
{
public abstract class ListSubCommandBase
{
protected abstract string CommandName { get; }
protected abstract string LocalizedDisplayName { get; }
protected abstract string LocalizedDescription { get; }
protected abstract IListSubCommand CreateIListSubCommand(string fileOrDirectory);
internal CommandLineApplication Create(CommandLineApplication parentApp)
{
CommandLineApplication app = parentApp.Command(CommandName, throwOnUnexpectedArg: false);
app.FullName = LocalizedDisplayName;
app.Description = LocalizedDescription;
app.HelpOption("-h|--help");
app.OnExecute(() => {
try
{
if (!parentApp.Arguments.Any())
{
throw new GracefulException(
CommonLocalizableStrings.RequiredArgumentNotPassed,
Constants.ProjectOrSolutionArgumentName);
}
var projectOrDirectory = parentApp.Arguments.First().Value;
if (string.IsNullOrEmpty(projectOrDirectory))
{
projectOrDirectory = PathUtility.EnsureTrailingSlash(Directory.GetCurrentDirectory());
}
var listCommand = CreateIListSubCommand(projectOrDirectory);
if (listCommand.Items.Count == 0)
{
Reporter.Output.WriteLine(listCommand.LocalizedErrorMessageNoItemsFound);
return 0;
}
Reporter.Output.WriteLine($"{CommonLocalizableStrings.ProjectReferenceOneOrMore}");
Reporter.Output.WriteLine(new string('-', CommonLocalizableStrings.ProjectReferenceOneOrMore.Length));
foreach (var item in listCommand.Items)
{
Reporter.Output.WriteLine(item);
}
return 0;
}
catch (GracefulException e)
{
Reporter.Error.WriteLine(e.Message.Red());
app.ShowHelp();
return 1;
}
});
return app;
}
}
}

View file

@ -4,7 +4,6 @@
using System;
using System.Collections.Generic;
using Microsoft.DotNet.Cli;
using Microsoft.DotNet.Cli.CommandLine;
using Microsoft.DotNet.Tools.List.ProjectToProjectReferences;
using Microsoft.DotNet.Tools.List.ProjectsInSolution;
@ -14,11 +13,11 @@ namespace Microsoft.DotNet.Tools.List
{
protected override string CommandName => "list";
protected override string FullCommandNameLocalized => LocalizableStrings.NetListCommand;
internal override List<Func<CommandLineApplication, CommandLineApplication>> SubCommands =>
new List<Func<CommandLineApplication, CommandLineApplication>>
internal override List<Func<DotNetSubCommandBase>> SubCommands =>
new List<Func<DotNetSubCommandBase>>
{
ListProjectsInSolutionCommand.CreateApplication,
ListProjectToProjectReferencesCommand.CreateApplication,
ListProjectsInSolutionCommand.Create,
ListProjectToProjectReferencesCommand.Create,
};
public static int Run(string[] args)

View file

@ -2,52 +2,50 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using Microsoft.Build.Evaluation;
using Microsoft.DotNet.Cli.CommandLine;
using System.Collections.Generic;
using Microsoft.DotNet.Tools.List;
using Microsoft.DotNet.Cli;
using Microsoft.DotNet.Cli.Utils;
using System.Linq;
namespace Microsoft.DotNet.Tools.List.ProjectToProjectReferences
{
public class ListProjectToProjectReferences : IListSubCommand
internal class ListProjectToProjectReferencesCommand : DotNetSubCommandBase
{
private string _fileOrDirectory = null;
private IList<string> _items = new List<string>();
public ListProjectToProjectReferences(string fileOrDirectory)
public static DotNetSubCommandBase Create()
{
var command = new ListProjectToProjectReferencesCommand()
{
Name = "p2ps",
FullName = LocalizableStrings.AppFullName,
Description = LocalizableStrings.AppDescription,
};
command.HelpOption("-h|--help");
return command;
}
public override int Run(string fileOrDirectory)
{
_fileOrDirectory = fileOrDirectory;
var msbuildProj = MsbuildProject.FromFileOrDirectory(new ProjectCollection(), fileOrDirectory);
var p2ps = msbuildProj.GetProjectToProjectReferences();
if (!p2ps.Any())
{
Reporter.Output.WriteLine(string.Format(
CommonLocalizableStrings.NoReferencesFound,
CommonLocalizableStrings.P2P,
fileOrDirectory));
return 0;
}
Reporter.Output.WriteLine($"{CommonLocalizableStrings.ProjectReferenceOneOrMore}");
Reporter.Output.WriteLine(new string('-', CommonLocalizableStrings.ProjectReferenceOneOrMore.Length));
foreach (var p2p in p2ps)
{
_items.Add(p2p.Include);
Reporter.Output.WriteLine(p2p.Include);
}
}
public string LocalizedErrorMessageNoItemsFound => string.Format(
LocalizableStrings.NoReferencesFound,
CommonLocalizableStrings.P2P,
_fileOrDirectory);
public IList<string> Items => _items;
}
public class ListProjectToProjectReferencesCommand : ListSubCommandBase
{
protected override string CommandName => "p2ps";
protected override string LocalizedDisplayName => LocalizableStrings.AppFullName;
protected override string LocalizedDescription => LocalizableStrings.AppDescription;
protected override IListSubCommand CreateIListSubCommand(string fileOrDirectory)
{
return new ListProjectToProjectReferences(fileOrDirectory);
}
internal static CommandLineApplication CreateApplication(CommandLineApplication parentApp)
{
var command = new ListProjectToProjectReferencesCommand();
return command.Create(parentApp);
return 0;
}
}
}

View file

@ -1,46 +1,46 @@
// 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 Microsoft.DotNet.Cli.CommandLine;
using Microsoft.DotNet.Cli;
using Microsoft.DotNet.Cli.Sln.Internal;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Tools.Common;
using System.Collections.Generic;
using Microsoft.DotNet.Tools.List;
namespace Microsoft.DotNet.Tools.List.ProjectsInSolution
{
public class ListProjectsInSolution : IListSubCommand
internal class ListProjectsInSolutionCommand : DotNetSubCommandBase
{
private IList<string> _items = new List<string>();
public static DotNetSubCommandBase Create()
{
var command = new ListProjectsInSolutionCommand()
{
Name = "projects",
FullName = LocalizableStrings.AppFullName,
Description = LocalizableStrings.AppDescription,
};
public ListProjectsInSolution(string fileOrDirectory)
command.HelpOption("-h|--help");
return command;
}
public override int Run(string fileOrDirectory)
{
SlnFile slnFile = SlnFileFactory.CreateFromFileOrDirectory(fileOrDirectory);
foreach (var slnProject in slnFile.Projects)
if (slnFile.Projects.Count == 0)
{
_items.Add(slnProject.FilePath);
Reporter.Output.WriteLine(CommonLocalizableStrings.NoProjectsFound);
}
}
public string LocalizedErrorMessageNoItemsFound => CommonLocalizableStrings.NoProjectsFound;
public IList<string> Items => _items;
}
public class ListProjectsInSolutionCommand : ListSubCommandBase
{
protected override string CommandName => "projects";
protected override string LocalizedDisplayName => LocalizableStrings.AppFullName;
protected override string LocalizedDescription => LocalizableStrings.AppDescription;
protected override IListSubCommand CreateIListSubCommand(string fileOrDirectory)
{
return new ListProjectsInSolution(fileOrDirectory);
}
internal static CommandLineApplication CreateApplication(CommandLineApplication parentApp)
{
var command = new ListProjectsInSolutionCommand();
return command.Create(parentApp);
else
{
Reporter.Output.WriteLine($"{CommonLocalizableStrings.ProjectReferenceOneOrMore}");
Reporter.Output.WriteLine(new string('-', CommonLocalizableStrings.ProjectReferenceOneOrMore.Length));
foreach (var slnProject in slnFile.Projects)
{
Reporter.Output.WriteLine(slnProject.FilePath);
}
}
return 0;
}
}
}

View file

@ -4,7 +4,7 @@
using System;
using System.Collections.Generic;
using Microsoft.DotNet.Cli;
using Microsoft.DotNet.Cli.CommandLine;
using Microsoft.DotNet.Tools.Remove.ProjectFromSolution;
using Microsoft.DotNet.Tools.Remove.ProjectToProjectReference;
namespace Microsoft.DotNet.Tools.Remove
@ -13,10 +13,11 @@ namespace Microsoft.DotNet.Tools.Remove
{
protected override string CommandName => "remove";
protected override string FullCommandNameLocalized => LocalizableStrings.NetRemoveCommand;
internal override List<Func<CommandLineApplication, CommandLineApplication>> SubCommands =>
new List<Func<CommandLineApplication, CommandLineApplication>>
internal override List<Func<DotNetSubCommandBase>> SubCommands =>
new List<Func<DotNetSubCommandBase>>
{
RemoveProjectToProjectReferenceCommand.CreateApplication,
RemoveProjectFromSolutionCommand.Create,
RemoveProjectToProjectReferenceCommand.Create,
};
public static int Run(string[] args)

View file

@ -12,7 +12,5 @@ namespace Microsoft.DotNet.Tools.Remove.ProjectToProjectReference
public const string AppHelpText = "Project to project references to remove";
public const string CmdFrameworkDescription = "Remove reference only when targetting a specific framework";
public const string SpecifyAtLeastOneReferenceToRemove = "You must specify at least one reference to delete. Please run dotnet delete --help for more information.";
}
}

View file

@ -2,75 +2,55 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using Microsoft.Build.Evaluation;
using Microsoft.DotNet.Cli;
using Microsoft.DotNet.Cli.CommandLine;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Tools.Common;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Microsoft.DotNet.Tools.Remove.ProjectToProjectReference
{
public class RemoveProjectToProjectReferenceCommand
internal class RemoveProjectToProjectReferenceCommand : DotNetSubCommandBase
{
internal static CommandLineApplication CreateApplication(CommandLineApplication parentApp)
private CommandOption _frameworkOption;
public static DotNetSubCommandBase Create()
{
CommandLineApplication app = parentApp.Command("p2p", throwOnUnexpectedArg: false);
app.FullName = LocalizableStrings.AppFullName;
app.Description = LocalizableStrings.AppDescription;
app.HandleRemainingArguments = true;
app.ArgumentSeparatorHelpText = LocalizableStrings.AppHelpText;
var command = new RemoveProjectToProjectReferenceCommand()
{
Name = "p2p",
FullName = LocalizableStrings.AppFullName,
Description = LocalizableStrings.AppDescription,
HandleRemainingArguments = true,
ArgumentSeparatorHelpText = LocalizableStrings.AppHelpText,
};
app.HelpOption("-h|--help");
command.HelpOption("-h|--help");
CommandOption frameworkOption = app.Option(
$"-f|--framework <{CommonLocalizableStrings.CmdFramework}>",
LocalizableStrings.CmdFrameworkDescription,
CommandOptionType.SingleValue);
command._frameworkOption = command.Option(
$"-f|--framework <{CommonLocalizableStrings.CmdFramework}>",
LocalizableStrings.CmdFrameworkDescription,
CommandOptionType.SingleValue);
app.OnExecute(() => {
try
{
if (!parentApp.Arguments.Any())
{
throw new GracefulException(CommonLocalizableStrings.RequiredArgumentNotPassed, Constants.ProjectOrSolutionArgumentName);
}
return command;
}
var projectOrDirectory = parentApp.Arguments.First().Value;
if (string.IsNullOrEmpty(projectOrDirectory))
{
projectOrDirectory = PathUtility.EnsureTrailingSlash(Directory.GetCurrentDirectory());
}
public override int Run(string fileOrDirectory)
{
var msbuildProj = MsbuildProject.FromFileOrDirectory(new ProjectCollection(), fileOrDirectory);
if (RemainingArguments.Count == 0)
{
throw new GracefulException(CommonLocalizableStrings.SpecifyAtLeastOneReferenceToRemove);
}
var msbuildProj = MsbuildProject.FromFileOrDirectory(new ProjectCollection(), projectOrDirectory);
int numberOfRemovedReferences = msbuildProj.RemoveProjectToProjectReferences(
_frameworkOption.Value(),
RemainingArguments);
if (app.RemainingArguments.Count == 0)
{
throw new GracefulException(LocalizableStrings.SpecifyAtLeastOneReferenceToRemove);
}
if (numberOfRemovedReferences != 0)
{
msbuildProj.ProjectRootElement.Save();
}
List<string> references = app.RemainingArguments;
int numberOfRemovedReferences = msbuildProj.RemoveProjectToProjectReferences(
frameworkOption.Value(),
references);
if (numberOfRemovedReferences != 0)
{
msbuildProj.ProjectRootElement.Save();
}
return 0;
}
catch (GracefulException e)
{
Reporter.Error.WriteLine(e.Message.Red());
app.ShowHelp();
return 1;
}
});
return app;
return 0;
}
}
}

View file

@ -0,0 +1,14 @@
// 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.
namespace Microsoft.DotNet.Tools.Remove.ProjectFromSolution
{
internal class LocalizableStrings
{
public const string AppFullName = ".NET Remove Project from Solution Command";
public const string AppDescription = "Command to remove projects from a solution";
public const string AppHelpText = "Projects to remove from a solution";
}
}

View file

@ -0,0 +1,89 @@
// 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 Microsoft.DotNet.Cli;
using Microsoft.DotNet.Cli.Sln.Internal;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Tools.Common;
using System;
using System.IO;
using System.Linq;
namespace Microsoft.DotNet.Tools.Remove.ProjectFromSolution
{
internal class RemoveProjectFromSolutionCommand : DotNetSubCommandBase
{
public static DotNetSubCommandBase Create()
{
var command = new RemoveProjectFromSolutionCommand()
{
Name = "project",
FullName = LocalizableStrings.AppFullName,
Description = LocalizableStrings.AppDescription,
HandleRemainingArguments = true,
ArgumentSeparatorHelpText = LocalizableStrings.AppHelpText,
};
command.HelpOption("-h|--help");
return command;
}
public override int Run(string fileOrDirectory)
{
SlnFile slnFile = SlnFileFactory.CreateFromFileOrDirectory(fileOrDirectory);
if (RemainingArguments.Count == 0)
{
throw new GracefulException(CommonLocalizableStrings.SpecifyAtLeastOneProjectToRemove);
}
var relativeProjectPaths = RemainingArguments.Select((p) =>
PathUtility.GetRelativePath(
PathUtility.EnsureTrailingSlash(slnFile.BaseDirectory),
Path.GetFullPath(p))).ToList();
bool slnChanged = false;
foreach (var path in relativeProjectPaths)
{
slnChanged |= RemoveProject(slnFile, path);
}
if (slnChanged)
{
slnFile.Write();
}
return 0;
}
private bool RemoveProject(SlnFile slnFile, string projectPath)
{
var projectPathNormalized = PathUtility.GetPathWithBackSlashes(projectPath);
var projectsToRemove = slnFile.Projects.Where((p) =>
string.Equals(p.FilePath, projectPathNormalized, StringComparison.OrdinalIgnoreCase)).ToList();
bool projectRemoved = false;
if (projectsToRemove.Count == 0)
{
Reporter.Output.WriteLine(string.Format(
CommonLocalizableStrings.ProjectReferenceCouldNotBeFound,
projectPath));
}
else
{
foreach (var slnProject in projectsToRemove)
{
slnFile.Projects.Remove(slnProject);
Reporter.Output.WriteLine(
string.Format(CommonLocalizableStrings.ProjectReferenceRemoved, slnProject.FilePath));
}
projectRemoved = true;
}
return projectRemoved;
}
}
}

View file

@ -14,6 +14,21 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
{
public class GivenDotnetAddP2P : TestBase
{
private const string HelpText = @".NET Add Project to Project (p2p) reference Command
Usage: dotnet add <PROJECT_OR_SOLUTION> p2p [options] [args]
Arguments:
<PROJECT_OR_SOLUTION> The project or solution to operation on. If a file is not specified, the current directory is searched.
Options:
-h|--help Show help information
-f|--framework <FRAMEWORK> Add reference only when targetting a specific framework
Args:
Project to project references to add
";
const string FrameworkNet451Arg = "-f net451";
const string ConditionFrameworkNet451 = "== 'net451'";
const string FrameworkNetCoreApp10Arg = "-f netcoreapp1.0";
@ -77,7 +92,18 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
{
var cmd = new AddP2PCommand().Execute(helpArg);
cmd.Should().Pass();
cmd.StdOut.Should().Contain("Usage");
cmd.StdOut.Should().Be(HelpText);
}
[Theory]
[InlineData("")]
[InlineData("unknownCommandName")]
public void WhenNoCommandIsPassedItPrintsError(string commandName)
{
var cmd = new DotnetCommand()
.ExecuteWithCapturedOutput($"add {commandName}");
cmd.Should().Fail();
cmd.StdErr.Should().Be("Required command was not provided.");
}
[Fact]
@ -87,7 +113,8 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
.WithProject("one two three")
.Execute("proj.csproj");
cmd.ExitCode.Should().NotBe(0);
cmd.StdErr.Should().Contain("Unrecognized command or argument");
cmd.StdErr.Should().Be("Unrecognized command or argument 'two'");
cmd.StdOut.Should().Be("Specify --help for a list of available options and commands.");
}
[Theory]
@ -102,8 +129,8 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
.WithProject(projName)
.Execute($"\"{setup.ValidRefCsprojPath}\"");
cmd.ExitCode.Should().NotBe(0);
cmd.StdErr.Should().Contain("Could not find");
cmd.StdOut.Should().Contain("Usage");
cmd.StdErr.Should().Be($"Could not find project or directory `{projName}`.");
cmd.StdOut.Should().Be(HelpText);
}
[Fact]
@ -117,8 +144,8 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
.WithProject(projName)
.Execute($"\"{setup.ValidRefCsprojPath}\"");
cmd.ExitCode.Should().NotBe(0);
cmd.StdErr.Should().Contain(" is invalid.");
cmd.StdOut.Should().Contain("Usage");
cmd.StdErr.Should().Be("Project `Broken/Broken.csproj` is invalid.");
cmd.StdOut.Should().Be(HelpText);
}
[Fact]
@ -126,12 +153,13 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
{
var setup = Setup();
var workingDir = Path.Combine(setup.TestRoot, "MoreThanOne");
var cmd = new AddP2PCommand()
.WithWorkingDirectory(Path.Combine(setup.TestRoot, "MoreThanOne"))
.WithWorkingDirectory(workingDir)
.Execute($"\"{setup.ValidRefCsprojRelToOtherProjPath}\"");
cmd.ExitCode.Should().NotBe(0);
cmd.StdErr.Should().Contain("more than one");
cmd.StdOut.Should().Contain("Usage");
cmd.StdErr.Should().Be($"Found more than one project in `{workingDir + Path.DirectorySeparatorChar}`. Please specify which one to use.");
cmd.StdOut.Should().Be(HelpText);
}
[Fact]
@ -143,8 +171,8 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
.WithWorkingDirectory(setup.TestRoot)
.Execute($"\"{setup.ValidRefCsprojPath}\"");
cmd.ExitCode.Should().NotBe(0);
cmd.StdErr.Should().Contain("not find any");
cmd.StdOut.Should().Contain("Usage");
cmd.StdErr.Should().Be($"Could not find any project in `{setup.TestRoot + Path.DirectorySeparatorChar}`.");
cmd.StdOut.Should().Be(HelpText);
}
[Fact]
@ -152,14 +180,14 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
{
var lib = NewLibWithFrameworks();
var setup = Setup();
int noCondBefore = lib.CsProj().NumberOfItemGroupsWithoutCondition();
var cmd = new AddP2PCommand()
.WithWorkingDirectory(setup.TestRoot)
.WithProject(lib.CsProjPath)
.Execute($"\"{setup.ValidRefCsprojPath}\"");
cmd.Should().Pass();
cmd.StdOut.Should().Contain("added to the project");
cmd.StdOut.Should().Be("Reference `DotnetAddP2PProjects\\ValidRef\\ValidRef.csproj` added to the project.");
cmd.StdErr.Should().BeEmpty();
var csproj = lib.CsProj();
csproj.NumberOfItemGroupsWithoutCondition().Should().Be(noCondBefore + 1);
@ -178,7 +206,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
.WithProject(lib.CsProjPath)
.Execute($"{FrameworkNet451Arg} \"{setup.ValidRefCsprojPath}\"");
cmd.Should().Pass();
cmd.StdOut.Should().Contain("added to the project");
cmd.StdOut.Should().Be("Reference `DotnetAddP2PProjects\\ValidRef\\ValidRef.csproj` added to the project.");
cmd.StdErr.Should().BeEmpty();
var csproj = lib.CsProj();
csproj.NumberOfItemGroupsWithConditionContaining(ConditionFrameworkNet451).Should().Be(condBefore + 1);
@ -203,7 +231,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
.WithProject(lib.CsProjName)
.Execute($"\"{setup.ValidRefCsprojPath}\"");
cmd.Should().Pass();
cmd.StdOut.Should().Contain("added to the project");
cmd.StdOut.Should().Be("Reference `DotnetAddP2PProjects\\ValidRef\\ValidRef.csproj` added to the project.");
var csproj = lib.CsProj();
csproj.NumberOfItemGroupsWithoutCondition().Should().Be(noCondBefore);
csproj.NumberOfProjectReferencesWithIncludeContaining(setup.ValidRefCsprojName).Should().Be(1);
@ -227,7 +255,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
.WithProject(lib.CsProjPath)
.Execute($"{FrameworkNet451Arg} \"{setup.ValidRefCsprojPath}\"");
cmd.Should().Pass();
cmd.StdOut.Should().Contain("added to the project");
cmd.StdOut.Should().Be("Reference `DotnetAddP2PProjects\\ValidRef\\ValidRef.csproj` added to the project.");
var csproj = lib.CsProj();
csproj.NumberOfItemGroupsWithConditionContaining(ConditionFrameworkNet451).Should().Be(condBefore);
csproj.NumberOfProjectReferencesWithIncludeAndConditionContaining(setup.ValidRefCsprojName, ConditionFrameworkNet451).Should().Be(1);
@ -251,7 +279,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
.WithProject(lib.CsProjPath)
.Execute($"{FrameworkNet451Arg} \"{setup.ValidRefCsprojPath}\"");
cmd.Should().Pass();
cmd.StdOut.Should().Contain("added to the project");
cmd.StdOut.Should().Be("Reference `DotnetAddP2PProjects\\ValidRef\\ValidRef.csproj` added to the project.");
var csproj = lib.CsProj();
csproj.NumberOfItemGroupsWithConditionContaining(ConditionFrameworkNet451).Should().Be(condBefore + 1);
csproj.NumberOfProjectReferencesWithIncludeAndConditionContaining(setup.ValidRefCsprojName, ConditionFrameworkNet451).Should().Be(1);
@ -275,7 +303,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
.WithProject(lib.CsProjPath)
.Execute($"\"{setup.ValidRefCsprojPath}\"");
cmd.Should().Pass();
cmd.StdOut.Should().Be("Reference `DotnetAddP2PProjects\\ValidRef\\ValidRef.csproj` added to the project.");
var csproj = lib.CsProj();
csproj.NumberOfItemGroupsWithoutCondition().Should().Be(noCondBefore + 1);
csproj.NumberOfProjectReferencesWithIncludeContaining(setup.ValidRefCsprojName).Should().Be(1);
@ -299,7 +327,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
.WithProject(lib.CsProjName)
.Execute($"\"{setup.ValidRefCsprojPath}\"");
cmd.Should().Pass();
cmd.StdOut.Should().Contain("already has a reference");
cmd.StdOut.Should().Be("Project already has a reference to `DotnetAddP2PProjects\\ValidRef\\ValidRef.csproj`.");
var csproj = lib.CsProj();
csproj.NumberOfItemGroupsWithoutCondition().Should().Be(noCondBefore);
@ -318,7 +346,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
.WithProject(proj.CsProjPath)
.Execute($"{FrameworkNet451Arg} \"{setup.LibCsprojRelPath}\"");
cmd.Should().Pass();
cmd.StdOut.Should().Contain("already has a reference");
cmd.StdOut.Should().Be("Project already has a reference to `..\\Lib\\Lib.csproj`.");
proj.CsProjContent().Should().BeEquivalentTo(contentBefore);
}
@ -340,7 +368,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
.WithProject(lib.CsProjPath)
.Execute($"{FrameworkNet451Arg} \"{setup.ValidRefCsprojPath}\"");
cmd.Should().Pass();
cmd.StdOut.Should().Contain("already has a reference");
cmd.StdOut.Should().Be("Project already has a reference to `DotnetAddP2PProjects\\ValidRef\\ValidRef.csproj`.");
lib.CsProjContent().Should().BeEquivalentTo(csprojContentBefore);
}
@ -356,7 +384,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
.WithProject(proj.CsProjName)
.Execute($"{FrameworkNet451Arg} \"{setup.LibCsprojRelPath}\"");
cmd.Should().Pass();
cmd.StdOut.Should().Contain("already has a reference");
cmd.StdOut.Should().Be("Project already has a reference to `..\\Lib\\Lib.csproj`.");
proj.CsProjContent().Should().BeEquivalentTo(contentBefore);
}
@ -372,7 +400,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
.WithProject(proj.CsProjName)
.Execute($"\"{setup.LibCsprojRelPath}\"");
cmd.Should().Pass();
cmd.StdOut.Should().Contain("already has a reference");
cmd.StdOut.Should().Be("Project already has a reference to `..\\Lib\\Lib.csproj`.");
proj.CsProjContent().Should().BeEquivalentTo(contentBefore);
}
@ -388,7 +416,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
.WithProject(proj.CsProjPath)
.Execute($"\"{setup.ValidRefCsprojPath}\"");
cmd.Should().Pass();
cmd.StdOut.Should().Contain("added to the project");
cmd.StdOut.Should().Be("Reference `..\\ValidRef\\ValidRef.csproj` added to the project.");
var csproj = proj.CsProj();
csproj.NumberOfItemGroupsWithoutCondition().Should().Be(noCondBefore + 1);
csproj.NumberOfProjectReferencesWithIncludeContaining(setup.ValidRefCsprojName).Should().Be(1);
@ -406,7 +434,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
.WithProject(proj.CsProjName)
.Execute($"{FrameworkNet451Arg} \"{setup.LibCsprojRelPath}\"");
cmd.Should().Pass();
cmd.StdOut.Should().Contain("already has a reference");
cmd.StdOut.Should().Be("Project already has a reference to `..\\Lib\\Lib.csproj`.");
proj.CsProjContent().Should().BeEquivalentTo(contentBefore);
}
@ -422,7 +450,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
.WithProject(proj.CsProjPath)
.Execute($"{FrameworkNet451Arg} \"{setup.ValidRefCsprojPath}\"");
cmd.Should().Pass();
cmd.StdOut.Should().Contain("added to the project");
cmd.StdOut.Should().Be("Reference `..\\ValidRef\\ValidRef.csproj` added to the project.");
var csproj = proj.CsProj();
csproj.NumberOfItemGroupsWithConditionContaining(ConditionFrameworkNet451).Should().Be(condBefore + 1);
csproj.NumberOfProjectReferencesWithIncludeAndConditionContaining(setup.ValidRefCsprojName, ConditionFrameworkNet451).Should().Be(1);
@ -440,7 +468,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
.WithProject(proj.CsProjPath)
.Execute($"\"{setup.ValidRefCsprojPath}\"");
cmd.Should().Pass();
cmd.StdOut.Should().Contain("added to the project");
cmd.StdOut.Should().Be("Reference `..\\ValidRef\\ValidRef.csproj` added to the project.");
var csproj = proj.CsProj();
csproj.NumberOfItemGroupsWithoutCondition().Should().Be(noCondBefore);
csproj.NumberOfProjectReferencesWithIncludeContaining(setup.ValidRefCsprojName).Should().Be(1);
@ -449,6 +477,9 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
[Fact]
public void ItAddsMultipleRefsNoCondToTheSameItemGroup()
{
const string OutputText = @"Reference `DotnetAddP2PProjects\Lib\Lib.csproj` added to the project.
Reference `DotnetAddP2PProjects\ValidRef\ValidRef.csproj` added to the project.";
var lib = NewLibWithFrameworks();
var setup = Setup();
@ -458,7 +489,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
.WithProject(lib.CsProjPath)
.Execute($"\"{setup.LibCsprojPath}\" \"{setup.ValidRefCsprojPath}\"");
cmd.Should().Pass();
cmd.StdOut.Should().Contain("added to the project").And.NotContain("already has a reference");
cmd.StdOut.Should().Be(OutputText);
var csproj = lib.CsProj();
csproj.NumberOfItemGroupsWithoutCondition().Should().Be(noCondBefore + 1);
csproj.NumberOfProjectReferencesWithIncludeContaining(setup.ValidRefCsprojName).Should().Be(1);
@ -468,6 +499,9 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
[Fact]
public void ItAddsMultipleRefsWithCondToTheSameItemGroup()
{
const string OutputText = @"Reference `DotnetAddP2PProjects\Lib\Lib.csproj` added to the project.
Reference `DotnetAddP2PProjects\ValidRef\ValidRef.csproj` added to the project.";
var lib = NewLibWithFrameworks();
var setup = Setup();
@ -477,7 +511,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
.WithProject(lib.CsProjPath)
.Execute($"{FrameworkNet451Arg} \"{setup.LibCsprojPath}\" \"{setup.ValidRefCsprojPath}\"");
cmd.Should().Pass();
cmd.StdOut.Should().Contain("added to the project").And.NotContain("already has a reference");
cmd.StdOut.Should().Be(OutputText);
var csproj = lib.CsProj();
csproj.NumberOfItemGroupsWithConditionContaining(ConditionFrameworkNet451).Should().Be(noCondBefore + 1);
csproj.NumberOfProjectReferencesWithIncludeAndConditionContaining(setup.ValidRefCsprojName, ConditionFrameworkNet451).Should().Be(1);
@ -495,7 +529,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
.WithWorkingDirectory(lib.Path)
.Execute($"\"{setup.ValidRefCsprojPath}\"");
cmd.Should().Pass();
cmd.StdOut.Should().Contain("added to the project");
cmd.StdOut.Should().Be("Reference `DotnetAddP2PProjects\\ValidRef\\ValidRef.csproj` added to the project.");
cmd.StdErr.Should().BeEmpty();
var csproj = lib.CsProj();
csproj.NumberOfItemGroupsWithoutCondition().Should().Be(noCondBefore + 1);
@ -513,7 +547,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
.WithProject(lib.CsProjName)
.Execute($"\"{setup.ValidRefCsprojPath}\"");
cmd.Should().Pass();
cmd.StdOut.Should().Contain("added to the project");
cmd.StdOut.Should().Be("Reference `DotnetAddP2PProjects\\ValidRef\\ValidRef.csproj` added to the project.");
cmd.StdErr.Should().BeEmpty();
int state = 0;
@ -558,7 +592,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
.WithProject(lib.CsProjName)
.Execute("\"IDoNotExist.csproj\"");
cmd.Should().Fail();
cmd.StdErr.Should().Contain("does not exist");
cmd.StdErr.Should().Be("Reference IDoNotExist.csproj does not exist.");
lib.CsProjContent().Should().BeEquivalentTo(contentBefore);
}
@ -574,8 +608,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
.WithProject(lib.CsProjPath)
.Execute($"\"{setup.ValidRefCsprojPath}\" \"IDoNotExist.csproj\"");
cmd.Should().Fail();
cmd.StdErr.Should().Contain("does not exist");
cmd.StdErr.Should().NotMatchRegex("(.*does not exist.*){2,}");
cmd.StdErr.Should().Be("Reference IDoNotExist.csproj does not exist.");
lib.CsProjContent().Should().BeEquivalentTo(contentBefore);
}
@ -591,7 +624,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
.WithProject(lib.CsProjName)
.Execute($"\"{setup.ValidRefCsprojPath.Replace('\\', '/')}\"");
cmd.Should().Pass();
cmd.StdOut.Should().Contain("added to the project");
cmd.StdOut.Should().Be("Reference `DotnetAddP2PProjects\\ValidRef\\ValidRef.csproj` added to the project.");
cmd.StdErr.Should().BeEmpty();
var csproj = lib.CsProj();
csproj.NumberOfItemGroupsWithoutCondition().Should().Be(noCondBefore + 1);
@ -610,7 +643,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
.WithProject(setup.LibCsprojPath)
.Execute($"\"{setup.ValidRefCsprojRelPath}\"");
cmd.Should().Pass();
cmd.StdOut.Should().Contain("added to the project");
cmd.StdOut.Should().Be("Reference `..\\ValidRef\\ValidRef.csproj` added to the project.");
cmd.StdErr.Should().BeEmpty();
var csproj = proj.CsProj();
csproj.NumberOfItemGroupsWithoutCondition().Should().Be(noCondBefore + 1);
@ -629,7 +662,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
.WithProject(lib.CsProjPath)
.Execute($"{FrameworkNet451Arg} \"{net45lib.CsProjPath}\"");
cmd.Should().Pass();
cmd.StdOut.Should().Contain("added to the project");
cmd.StdOut.Should().Be("Reference `..\\Net45Lib\\Net45Lib.csproj` added to the project.");
var csproj = lib.CsProj();
csproj.NumberOfItemGroupsWithConditionContaining(ConditionFrameworkNet451).Should().Be(condBefore + 1);
csproj.NumberOfProjectReferencesWithIncludeAndConditionContaining(net45lib.CsProjName, ConditionFrameworkNet451).Should().Be(1);
@ -647,7 +680,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
.WithProject(net452netcoreapp10lib.CsProjPath)
.Execute($"\"{lib.CsProjPath}\"");
cmd.Should().Pass();
cmd.StdOut.Should().Contain("added to the project");
cmd.StdOut.Should().Be("Reference `..\\Lib\\Lib.csproj` added to the project.");
var csproj = net452netcoreapp10lib.CsProj();
csproj.NumberOfItemGroupsWithoutCondition().Should().Be(noCondBefore + 1);
csproj.NumberOfProjectReferencesWithIncludeContaining(lib.CsProjName).Should().Be(1);
@ -669,8 +702,8 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
.WithProject(lib.CsProjPath)
.Execute($"-f {framework} \"{net45lib.CsProjPath}\"");
cmd.Should().Fail();
cmd.StdErr.Should().MatchRegex(ProjectDoesNotTargetFrameworkErrorMessageRegEx);
cmd.StdErr.Should().Contain($"`{framework}`");
cmd.StdErr.Should().Be($"Project `{setup.LibCsprojPath}` does not target framework `{framework}`.");
lib.CsProjContent().Should().BeEquivalentTo(csProjContent);
}

View file

@ -14,6 +14,20 @@ namespace Microsoft.DotNet.Cli.Add.Proj.Tests
{
public class GivenDotnetAddProj : TestBase
{
private string HelpText = @".NET Add Project to Solution Command
Usage: dotnet add <PROJECT_OR_SOLUTION> project [options] [args]
Arguments:
<PROJECT_OR_SOLUTION> The project or solution to operation on. If a file is not specified, the current directory is searched.
Options:
-h|--help Show help information
Args:
Projects to add to solution
";
[Theory]
[InlineData("--help")]
[InlineData("-h")]
@ -22,7 +36,18 @@ namespace Microsoft.DotNet.Cli.Add.Proj.Tests
var cmd = new DotnetCommand()
.ExecuteWithCapturedOutput($"add project {helpArg}");
cmd.Should().Pass();
cmd.StdOut.Should().Contain("Usage");
cmd.StdOut.Should().Be(HelpText);
}
[Theory]
[InlineData("")]
[InlineData("unknownCommandName")]
public void WhenNoCommandIsPassedItPrintsError(string commandName)
{
var cmd = new DotnetCommand()
.ExecuteWithCapturedOutput($"add {commandName}");
cmd.Should().Fail();
cmd.StdErr.Should().Be("Required command was not provided.");
}
[Fact]
@ -31,7 +56,8 @@ namespace Microsoft.DotNet.Cli.Add.Proj.Tests
var cmd = new DotnetCommand()
.ExecuteWithCapturedOutput("add one.sln two.sln three.sln project");
cmd.Should().Fail();
cmd.StdErr.Should().Contain("Unrecognized command or argument");
cmd.StdErr.Should().Be("Unrecognized command or argument 'two.sln'");
cmd.StdOut.Should().Be("Specify --help for a list of available options and commands.");
}
[Theory]
@ -45,86 +71,103 @@ namespace Microsoft.DotNet.Cli.Add.Proj.Tests
var cmd = new DotnetCommand()
.ExecuteWithCapturedOutput($"add {solutionName} project p.csproj");
cmd.Should().Fail();
cmd.StdErr.Should().Contain("Could not find");
cmd.StdOut.Should().Contain("Usage:");
cmd.StdErr.Should().Be($"Could not find solution or directory `{solutionName}`.");
cmd.StdOut.Should().Be(HelpText);
}
[Fact]
public void WhenInvalidSolutionIsPassedItPrintsErrorAndUsage()
{
var projectDirectory = TestAssetsManager.CreateTestInstance("InvalidSolution")
.WithLockFiles()
.Path;
var projectDirectory = TestAssets
.Get("InvalidSolution")
.CreateInstance()
.WithSourceFiles()
.Root
.FullName;
var projectToAdd = Path.Combine("Lib", "Lib.csproj");
var cmd = new DotnetCommand()
.WithWorkingDirectory(projectDirectory)
.ExecuteWithCapturedOutput($"add InvalidSolution.sln project {projectToAdd}");
cmd.Should().Fail();
cmd.StdErr.Should().Contain("Invalid solution ");
cmd.StdOut.Should().Contain("Usage:");
cmd.StdErr.Should().Be("Invalid solution `InvalidSolution.sln`.");
cmd.StdOut.Should().Be(HelpText);
}
[Fact]
public void WhenInvalidSolutionIsFoundItPrintsErrorAndUsage()
{
var projectDirectory = TestAssetsManager.CreateTestInstance("InvalidSolution")
.WithLockFiles()
.Path;
var projectDirectory = TestAssets
.Get("InvalidSolution")
.CreateInstance()
.WithSourceFiles()
.Root
.FullName;
var solutionPath = Path.Combine(projectDirectory, "InvalidSolution.sln");
var projectToAdd = Path.Combine("Lib", "Lib.csproj");
var cmd = new DotnetCommand()
.WithWorkingDirectory(projectDirectory)
.ExecuteWithCapturedOutput($"add project {projectToAdd}");
cmd.Should().Fail();
cmd.StdErr.Should().Contain("Invalid solution ");
cmd.StdOut.Should().Contain("Usage:");
cmd.StdErr.Should().Be($"Invalid solution `{solutionPath}`.");
cmd.StdOut.Should().Be(HelpText);
}
[Fact]
public void WhenNoProjectIsPassedItPrintsErrorAndUsage()
{
var projectDirectory = TestAssetsManager.CreateTestInstance("TestAppWithSlnAndCsprojFiles")
.WithLockFiles()
.Path;
var projectDirectory = TestAssets
.Get("TestAppWithSlnAndCsprojFiles")
.CreateInstance()
.WithSourceFiles()
.Root
.FullName;
var cmd = new DotnetCommand()
.WithWorkingDirectory(projectDirectory)
.ExecuteWithCapturedOutput(@"add App.sln project");
cmd.Should().Fail();
cmd.StdErr.Should().Contain("You must specify at least one project to add.");
cmd.StdOut.Should().Contain("Usage:");
cmd.StdErr.Should().Be("You must specify at least one project to add.");
cmd.StdOut.Should().Be(HelpText);
}
[Fact]
public void WhenNoSolutionExistsInTheDirectoryItPrintsErrorAndUsage()
{
var projectDirectory = TestAssetsManager.CreateTestInstance("TestAppWithSlnAndCsprojFiles")
.WithLockFiles()
.Path;
var projectDirectory = TestAssets
.Get("TestAppWithSlnAndCsprojFiles")
.CreateInstance()
.WithSourceFiles()
.Root
.FullName;
var solutionPath = Path.Combine(projectDirectory, "App");
var cmd = new DotnetCommand()
.WithWorkingDirectory(Path.Combine(projectDirectory, "App"))
.WithWorkingDirectory(solutionPath)
.ExecuteWithCapturedOutput(@"add project App.csproj");
cmd.Should().Fail();
cmd.StdErr.Should().Contain("does not exist");
cmd.StdOut.Should().Contain("Usage:");
cmd.StdErr.Should().Be($"Specified solution file {solutionPath + Path.DirectorySeparatorChar} does not exist, or there is no solution file in the directory.");
cmd.StdOut.Should().Be(HelpText);
}
[Fact]
public void WhenMoreThanOneSolutionExistsInTheDirectoryItPrintsErrorAndUsage()
{
var projectDirectory = TestAssetsManager.CreateTestInstance("TestAppWithMultipleSlnFiles")
.WithLockFiles()
.Path;
var projectDirectory = TestAssets
.Get("TestAppWithMultipleSlnFiles")
.CreateInstance()
.WithSourceFiles()
.Root
.FullName;
var projectToAdd = Path.Combine("Lib", "Lib.csproj");
var cmd = new DotnetCommand()
.WithWorkingDirectory(projectDirectory)
.ExecuteWithCapturedOutput($"add project {projectToAdd}");
cmd.Should().Fail();
cmd.StdErr.Should().Contain("more than one");
cmd.StdOut.Should().Contain("Usage");
cmd.StdErr.Should().Be($"Found more than one solution file in {projectDirectory + Path.DirectorySeparatorChar}. Please specify which one to use.");
cmd.StdOut.Should().Be(HelpText);
}
[Theory]
@ -134,9 +177,12 @@ namespace Microsoft.DotNet.Cli.Add.Proj.Tests
string testAsset,
string projectGuid)
{
var projectDirectory = TestAssetsManager.CreateTestInstance(testAsset)
.WithLockFiles()
.Path;
var projectDirectory = TestAssets
.Get(testAsset)
.CreateInstance()
.WithSourceFiles()
.Root
.FullName;
var projectToAdd = "Lib/Lib.csproj";
var normalizedProjectPath = @"Lib\Lib.csproj";
@ -144,7 +190,7 @@ namespace Microsoft.DotNet.Cli.Add.Proj.Tests
.WithWorkingDirectory(projectDirectory)
.ExecuteWithCapturedOutput($"add App.sln project {projectToAdd}");
cmd.Should().Pass();
cmd.StdOut.Should().Contain("added to the solution");
cmd.StdOut.Should().Be($"Project `{Path.Combine("Lib", "Lib.csproj")}` added to the solution.");
cmd.StdErr.Should().BeEmpty();
var slnFile = SlnFile.Read(Path.Combine(projectDirectory, "App.sln"));
@ -174,25 +220,32 @@ namespace Microsoft.DotNet.Cli.Add.Proj.Tests
[Fact]
public void WhenSolutionAlreadyContainsProjectItDoesntDuplicate()
{
var projectDirectory = TestAssetsManager.CreateTestInstance("TestAppWithSlnAndExistingCsprojReferences")
.WithLockFiles()
.Path;
var projectDirectory = TestAssets
.Get("TestAppWithSlnAndExistingCsprojReferences")
.CreateInstance()
.WithSourceFiles()
.Root
.FullName;
var solutionPath = Path.Combine(projectDirectory, "App.sln");
var projectToAdd = Path.Combine("Lib", "Lib.csproj");
var cmd = new DotnetCommand()
.WithWorkingDirectory(projectDirectory)
.ExecuteWithCapturedOutput($"add App.sln project {projectToAdd}");
cmd.Should().Pass();
cmd.StdOut.Should().Contain("already contains project");
cmd.StdOut.Should().Be($"Solution {solutionPath} already contains project {projectToAdd}.");
cmd.StdErr.Should().BeEmpty();
}
[Fact]
public void WhenPassedMultipleProjectsAndOneOfthemDoesNotExistItCancelsWholeOperation()
{
var projectDirectory = TestAssetsManager.CreateTestInstance("TestAppWithSlnAndCsprojFiles")
.WithLockFiles()
.Path;
var projectDirectory = TestAssets
.Get("TestAppWithSlnAndCsprojFiles")
.CreateInstance()
.WithSourceFiles()
.Root
.FullName;
var slnFullPath = Path.Combine(projectDirectory, "App.sln");
var contentBefore = File.ReadAllText(slnFullPath);
@ -202,8 +255,7 @@ namespace Microsoft.DotNet.Cli.Add.Proj.Tests
.WithWorkingDirectory(projectDirectory)
.ExecuteWithCapturedOutput($"add App.sln project {projectToAdd} idonotexist.csproj");
cmd.Should().Fail();
cmd.StdErr.Should().Contain("does not exist");
cmd.StdErr.Should().NotMatchRegex("(.*does not exist.*){2,}");
cmd.StdErr.Should().Be("Project `idonotexist.csproj` does not exist.");
File.ReadAllText(slnFullPath)
.Should().BeEquivalentTo(contentBefore);

View file

@ -7,7 +7,6 @@
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
<AssemblyName>dotnet-add-proj.Tests</AssemblyName>
<PackageTargetFallback Condition=" '$(TargetFramework)' == 'netcoreapp1.0' ">$(PackageTargetFallback);dotnet5.4;portable-net451+win8</PackageTargetFallback>
<DefineConstants>$(DefineConstants);DISABLE_TRACE</DefineConstants>
</PropertyGroup>
<ItemGroup>
<Compile Include="**\*.cs" />
@ -21,10 +20,6 @@
<ProjectReference Include="..\..\src\Microsoft.DotNet.TestFramework\Microsoft.DotNet.TestFramework.csproj" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net46' ">
<Reference Include="System.Runtime" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Sdk">
<Version>$(CLI_NETSDK_Version)</Version>

View file

@ -13,11 +13,20 @@ namespace Microsoft.DotNet.Cli.List.P2P.Tests
{
public class GivenDotnetListP2Ps : TestBase
{
private const string HelpText = @".NET Core Project-to-Project dependency viewer
Usage: dotnet list <PROJECT_OR_SOLUTION> p2ps [options]
Arguments:
<PROJECT_OR_SOLUTION> The project or solution to operation on. If a file is not specified, the current directory is searched.
Options:
-h|--help Show help information";
const string FrameworkNet451Arg = "-f net451";
const string ConditionFrameworkNet451 = "== 'net451'";
const string FrameworkNetCoreApp10Arg = "-f netcoreapp1.0";
const string ConditionFrameworkNetCoreApp10 = "== 'netcoreapp1.0'";
const string UsageText = "Usage: dotnet list <PROJECT_OR_SOLUTION> p2ps";
[Theory]
[InlineData("--help")]
@ -26,7 +35,18 @@ namespace Microsoft.DotNet.Cli.List.P2P.Tests
{
var cmd = new ListP2PsCommand().Execute(helpArg);
cmd.Should().Pass();
cmd.StdOut.Should().Contain("Usage");
cmd.StdOut.Should().Be(HelpText);
}
[Theory]
[InlineData("")]
[InlineData("unknownCommandName")]
public void WhenNoCommandIsPassedItPrintsError(string commandName)
{
var cmd = new DotnetCommand()
.ExecuteWithCapturedOutput($"list {commandName}");
cmd.Should().Fail();
cmd.StdErr.Should().Be("Required command was not provided.");
}
[Fact]
@ -36,7 +56,7 @@ namespace Microsoft.DotNet.Cli.List.P2P.Tests
.WithProject("one two three")
.Execute("proj.csproj");
cmd.ExitCode.Should().NotBe(0);
cmd.StdErr.Should().Contain("Unrecognized command or argument");
cmd.StdErr.Should().Be("Unrecognized command or argument 'two'");
}
[Theory]
@ -51,8 +71,8 @@ namespace Microsoft.DotNet.Cli.List.P2P.Tests
.WithProject(projName)
.Execute($"\"{setup.ValidRefCsprojPath}\"");
cmd.ExitCode.Should().NotBe(0);
cmd.StdErr.Should().Contain("Could not find");
cmd.StdOut.Should().Contain(UsageText);
cmd.StdErr.Should().Be($"Could not find project or directory `{projName}`.");
cmd.StdOut.Should().Be(HelpText);
}
[Fact]
@ -66,8 +86,8 @@ namespace Microsoft.DotNet.Cli.List.P2P.Tests
.WithProject(projName)
.Execute($"\"{setup.ValidRefCsprojPath}\"");
cmd.ExitCode.Should().NotBe(0);
cmd.StdErr.Should().Contain(" is invalid.");
cmd.StdOut.Should().Contain(UsageText);
cmd.StdErr.Should().Be("Project `Broken/Broken.csproj` is invalid.");
cmd.StdOut.Should().Be(HelpText);
}
[Fact]
@ -75,12 +95,13 @@ namespace Microsoft.DotNet.Cli.List.P2P.Tests
{
var setup = Setup();
var workingDir = Path.Combine(setup.TestRoot, "MoreThanOne");
var cmd = new ListP2PsCommand()
.WithWorkingDirectory(Path.Combine(setup.TestRoot, "MoreThanOne"))
.WithWorkingDirectory(workingDir)
.Execute($"\"{setup.ValidRefCsprojRelToOtherProjPath}\"");
cmd.ExitCode.Should().NotBe(0);
cmd.StdErr.Should().Contain("more than one");
cmd.StdOut.Should().Contain(UsageText);
cmd.StdErr.Should().Be($"Found more than one project in `{workingDir + Path.DirectorySeparatorChar}`. Please specify which one to use.");
cmd.StdOut.Should().Be(HelpText);
}
[Fact]
@ -92,8 +113,8 @@ namespace Microsoft.DotNet.Cli.List.P2P.Tests
.WithWorkingDirectory(setup.TestRoot)
.Execute($"\"{setup.ValidRefCsprojPath}\"");
cmd.ExitCode.Should().NotBe(0);
cmd.StdErr.Should().Contain("not find any");
cmd.StdOut.Should().Contain(UsageText);
cmd.StdErr.Should().Be($"Could not find any project in `{setup.TestRoot + Path.DirectorySeparatorChar}`.");
cmd.StdOut.Should().Be(HelpText);
}
[Fact]
@ -105,12 +126,16 @@ namespace Microsoft.DotNet.Cli.List.P2P.Tests
.WithProject(lib.CsProjPath)
.Execute();
cmd.Should().Pass();
cmd.StdOut.Should().Contain("There are no Project to Project references in project");
cmd.StdOut.Should().Be($"There are no Project to Project references in project {lib.CsProjPath}. ;; Project to Project is the type of the item being requested (project, package, p2p) and {lib.CsProjPath} is the object operated on (a project file or a solution file). ");
}
[Fact]
public void ItPrintsSingleReference()
{
const string OutputText = @"Project reference(s)
--------------------
..\ItPrintsSingleReferenceref\ItPrintsSingleReferenceref.csproj";
var lib = NewLib("ItPrintsSingleReference", "lib");
string ref1 = NewLib("ItPrintsSingleReference", "ref").CsProjPath;
AddValidRef(ref1, lib);
@ -119,13 +144,18 @@ namespace Microsoft.DotNet.Cli.List.P2P.Tests
.WithProject(lib.CsProjPath)
.Execute();
cmd.Should().Pass();
cmd.StdOut.Should().Contain("Project reference(s)");
cmd.StdOut.Should().Contain(@"..\ItPrintsSingleReferenceref\ItPrintsSingleReferenceref.csproj");
cmd.StdOut.Should().Be(OutputText);
}
[Fact]
public void ItPrintsMultipleReferences()
{
const string OutputText = @"Project reference(s)
--------------------
..\ItPrintsSingleReferenceref1\ItPrintsSingleReferenceref1.csproj
..\ItPrintsSingleReferenceref2\ItPrintsSingleReferenceref2.csproj
..\ItPrintsSingleReferenceref3\ItPrintsSingleReferenceref3.csproj";
var lib = NewLib("ItPrintsSingleReference", "lib");
string ref1 = NewLib("ItPrintsSingleReference", "ref1").CsProjPath;
string ref2 = NewLib("ItPrintsSingleReference", "ref2").CsProjPath;
@ -139,10 +169,7 @@ namespace Microsoft.DotNet.Cli.List.P2P.Tests
.WithProject(lib.CsProjPath)
.Execute();
cmd.Should().Pass();
cmd.StdOut.Should().Contain("Project reference(s)");
cmd.StdOut.Should().Contain(@"..\ItPrintsSingleReferenceref1\ItPrintsSingleReferenceref1.csproj");
cmd.StdOut.Should().Contain(@"..\ItPrintsSingleReferenceref2\ItPrintsSingleReferenceref2.csproj");
cmd.StdOut.Should().Contain(@"..\ItPrintsSingleReferenceref3\ItPrintsSingleReferenceref3.csproj");
cmd.StdOut.Should().Be(OutputText);
}
private TestSetup Setup([System.Runtime.CompilerServices.CallerMemberName] string callingMethod = nameof(Setup), string identifier = "")

View file

@ -31,7 +31,7 @@ Options:
var cmd = new DotnetCommand()
.ExecuteWithCapturedOutput($"list projects {helpArg}");
cmd.Should().Pass();
cmd.StdOut.Should().Contain(HelpText);
cmd.StdOut.Should().Be(HelpText);
}
[Theory]
@ -42,7 +42,7 @@ Options:
var cmd = new DotnetCommand()
.ExecuteWithCapturedOutput($"list {commandName}");
cmd.Should().Fail();
cmd.StdErr.Should().Contain("Required command was not provided.");
cmd.StdErr.Should().Be("Required command was not provided.");
}
[Fact]
@ -51,7 +51,7 @@ Options:
var cmd = new DotnetCommand()
.ExecuteWithCapturedOutput("list one.sln two.sln three.sln projects");
cmd.Should().Fail();
cmd.StdErr.Should().Contain("Unrecognized command or argument 'two.sln'");
cmd.StdErr.Should().Be("Unrecognized command or argument 'two.sln'");
}
[Theory]
@ -65,8 +65,8 @@ Options:
var cmd = new DotnetCommand()
.ExecuteWithCapturedOutput($"list {solutionName} projects");
cmd.Should().Fail();
cmd.StdErr.Should().Contain($"Could not find solution or directory `{solutionName}`");
cmd.StdOut.Should().Contain(HelpText);
cmd.StdErr.Should().Be($"Could not find solution or directory `{solutionName}`.");
cmd.StdOut.Should().Be(HelpText);
}
[Fact]
@ -83,8 +83,8 @@ Options:
.WithWorkingDirectory(projectDirectory)
.ExecuteWithCapturedOutput("list InvalidSolution.sln projects");
cmd.Should().Fail();
cmd.StdErr.Should().Contain("Invalid solution `InvalidSolution.sln`");
cmd.StdOut.Should().Contain(HelpText);
cmd.StdErr.Should().Be("Invalid solution `InvalidSolution.sln`.");
cmd.StdOut.Should().Be(HelpText);
}
[Fact]
@ -102,8 +102,8 @@ Options:
.WithWorkingDirectory(projectDirectory)
.ExecuteWithCapturedOutput("list projects");
cmd.Should().Fail();
cmd.StdErr.Should().Contain($"Invalid solution `{solutionFullPath}`");
cmd.StdOut.Should().Contain(HelpText);
cmd.StdErr.Should().Be($"Invalid solution `{solutionFullPath}`.");
cmd.StdOut.Should().Be(HelpText);
}
[Fact]
@ -121,8 +121,8 @@ Options:
.WithWorkingDirectory(solutionDir)
.ExecuteWithCapturedOutput("list projects");
cmd.Should().Fail();
cmd.StdErr.Should().Contain($"Specified solution file {solutionDir + Path.DirectorySeparatorChar} does not exist, or there is no solution file in the directory");
cmd.StdOut.Should().Contain(HelpText);
cmd.StdErr.Should().Be($"Specified solution file {solutionDir + Path.DirectorySeparatorChar} does not exist, or there is no solution file in the directory.");
cmd.StdOut.Should().Be(HelpText);
}
[Fact]
@ -139,8 +139,8 @@ Options:
.WithWorkingDirectory(projectDirectory)
.ExecuteWithCapturedOutput("list projects");
cmd.Should().Fail();
cmd.StdErr.Should().Contain($"Found more than one solution file in {projectDirectory + Path.DirectorySeparatorChar}. Please specify which one to use.");
cmd.StdOut.Should().Contain(HelpText);
cmd.StdErr.Should().Be($"Found more than one solution file in {projectDirectory + Path.DirectorySeparatorChar}. Please specify which one to use.");
cmd.StdOut.Should().Be(HelpText);
}
[Fact]
@ -157,12 +157,17 @@ Options:
.WithWorkingDirectory(projectDirectory)
.ExecuteWithCapturedOutput("list projects");
cmd.Should().Pass();
cmd.StdOut.Should().Contain("No projects found in the solution.");
cmd.StdOut.Should().Be("No projects found in the solution.");
}
[Fact]
public void WhenProjectReferencesArePresentInTheSolutionItListsThem()
{
const string OutputText = @"Project reference(s)
--------------------
App\App.csproj
Lib\Lib.csproj";
var projectDirectory = TestAssets
.Get("TestAppWithSlnAndExistingCsprojReferences")
.CreateInstance()
@ -174,9 +179,7 @@ Options:
.WithWorkingDirectory(projectDirectory)
.ExecuteWithCapturedOutput("list projects");
cmd.Should().Pass();
cmd.StdOut.Should().Contain("Project reference(s)");
cmd.StdOut.Should().Contain(@"App\App.csproj");
cmd.StdOut.Should().Contain(@"Lib\Lib.csproj");
cmd.StdOut.Should().Be(OutputText);
}
}
}

View file

@ -13,6 +13,21 @@ namespace Microsoft.DotNet.Cli.Remove.P2P.Tests
{
public class GivenDotnetRemoveP2P : TestBase
{
private const string HelpText = @".NET Remove Project to Project (p2p) reference Command
Usage: dotnet remove <PROJECT_OR_SOLUTION> p2p [options] [args]
Arguments:
<PROJECT_OR_SOLUTION> The project or solution to operation on. If a file is not specified, the current directory is searched.
Options:
-h|--help Show help information
-f|--framework <FRAMEWORK> Remove reference only when targetting a specific framework
Args:
Project to project references to remove
";
const string FrameworkNet451Arg = "-f net451";
const string ConditionFrameworkNet451 = "== 'net451'";
const string FrameworkNetCoreApp10Arg = "-f netcoreapp1.0";
@ -103,7 +118,18 @@ namespace Microsoft.DotNet.Cli.Remove.P2P.Tests
{
var cmd = new RemoveP2PCommand().Execute(helpArg);
cmd.Should().Pass();
cmd.StdOut.Should().Contain("Usage");
cmd.StdOut.Should().Be(HelpText);
}
[Theory]
[InlineData("")]
[InlineData("unknownCommandName")]
public void WhenNoCommandIsPassedItPrintsError(string commandName)
{
var cmd = new DotnetCommand()
.ExecuteWithCapturedOutput($"remove {commandName}");
cmd.Should().Fail();
cmd.StdErr.Should().Be("Required command was not provided.");
}
[Fact]
@ -113,7 +139,8 @@ namespace Microsoft.DotNet.Cli.Remove.P2P.Tests
.WithProject("one two three")
.Execute("proj.csproj");
cmd.ExitCode.Should().NotBe(0);
cmd.StdErr.Should().Contain("Unrecognized command or argument");
cmd.StdErr.Should().Be("Unrecognized command or argument 'two'");
cmd.StdOut.Should().Be("Specify --help for a list of available options and commands.");
}
[Theory]
@ -128,8 +155,8 @@ namespace Microsoft.DotNet.Cli.Remove.P2P.Tests
.WithProject(projName)
.Execute($"\"{setup.ValidRefCsprojPath}\"");
cmd.ExitCode.Should().NotBe(0);
cmd.StdErr.Should().Contain("Could not find");
cmd.StdOut.Should().Contain("Usage");
cmd.StdErr.Should().Be($"Could not find project or directory `{projName}`.");
cmd.StdOut.Should().Be(HelpText);
}
[Fact]
@ -143,8 +170,8 @@ namespace Microsoft.DotNet.Cli.Remove.P2P.Tests
.WithProject(projName)
.Execute($"\"{setup.ValidRefCsprojPath}\"");
cmd.ExitCode.Should().NotBe(0);
cmd.StdErr.Should().Contain(" is invalid.");
cmd.StdOut.Should().Contain("Usage");
cmd.StdErr.Should().Be("Project `Broken/Broken.csproj` is invalid.");
cmd.StdOut.Should().Be(HelpText);
}
[Fact]
@ -152,12 +179,13 @@ namespace Microsoft.DotNet.Cli.Remove.P2P.Tests
{
var setup = Setup();
var workingDir = Path.Combine(setup.TestRoot, "MoreThanOne");
var cmd = new RemoveP2PCommand()
.WithWorkingDirectory(Path.Combine(setup.TestRoot, "MoreThanOne"))
.WithWorkingDirectory(workingDir)
.Execute($"\"{setup.ValidRefCsprojRelToOtherProjPath}\"");
cmd.ExitCode.Should().NotBe(0);
cmd.StdErr.Should().Contain("more than one");
cmd.StdOut.Should().Contain("Usage");
cmd.StdErr.Should().Be($"Found more than one project in `{workingDir + Path.DirectorySeparatorChar}`. Please specify which one to use.");
cmd.StdOut.Should().Be(HelpText);
}
[Fact]
@ -169,8 +197,8 @@ namespace Microsoft.DotNet.Cli.Remove.P2P.Tests
.WithWorkingDirectory(setup.TestRoot)
.Execute($"\"{setup.ValidRefCsprojPath}\"");
cmd.ExitCode.Should().NotBe(0);
cmd.StdErr.Should().Contain("not find any");
cmd.StdOut.Should().Contain("Usage");
cmd.StdErr.Should().Be($"Could not find any project in `{setup.TestRoot + Path.DirectorySeparatorChar}`.");
cmd.StdOut.Should().Be(HelpText);
}
[Fact]
@ -186,7 +214,7 @@ namespace Microsoft.DotNet.Cli.Remove.P2P.Tests
.WithProject(lib.CsProjPath)
.Execute($"\"{libref.CsProjPath}\"");
cmd.Should().Pass();
cmd.StdOut.Should().MatchRegex("(^|[\r\n])Project reference[^\r\n]*removed.($|[\r\n])");
cmd.StdOut.Should().Be($"Project reference `{Path.Combine(TestSetup.ProjectName, "Lib", setup.LibCsprojName)}` removed.");
var csproj = lib.CsProj();
csproj.NumberOfItemGroupsWithoutCondition().Should().Be(noCondBefore - 1);
csproj.NumberOfProjectReferencesWithIncludeContaining(libref.Name).Should().Be(0);
@ -205,7 +233,7 @@ namespace Microsoft.DotNet.Cli.Remove.P2P.Tests
.WithProject(lib.CsProjPath)
.Execute($"{FrameworkNet451Arg} \"{libref.CsProjPath}\"");
cmd.Should().Pass();
cmd.StdOut.Should().MatchRegex("(^|[\r\n])Project reference[^\r\n]*removed.($|[\r\n])");
cmd.StdOut.Should().Be($"Project reference `{Path.Combine(TestSetup.ProjectName, "Lib", setup.LibCsprojName)}` removed.");
var csproj = lib.CsProj();
csproj.NumberOfItemGroupsWithConditionContaining(ConditionFrameworkNet451).Should().Be(condBefore - 1);
csproj.NumberOfProjectReferencesWithIncludeAndConditionContaining(libref.Name, ConditionFrameworkNet451).Should().Be(0);
@ -225,8 +253,7 @@ namespace Microsoft.DotNet.Cli.Remove.P2P.Tests
.WithProject(lib.CsProjPath)
.Execute($"\"{libref.CsProjPath}\"");
cmd.Should().Pass();
cmd.StdOut.Should().MatchRegex("(^|[\r\n])Project reference[^\r\n]*removed.($|[\r\n])");
cmd.StdOut.Should().NotContain(validref.Name);
cmd.StdOut.Should().Be($"Project reference `{Path.Combine(TestSetup.ProjectName, "Lib", setup.LibCsprojName)}` removed.");
var csproj = lib.CsProj();
csproj.NumberOfItemGroupsWithoutCondition().Should().Be(noCondBefore);
csproj.NumberOfProjectReferencesWithIncludeContaining(libref.Name).Should().Be(0);
@ -245,7 +272,7 @@ namespace Microsoft.DotNet.Cli.Remove.P2P.Tests
.WithProject(lib.CsProjPath)
.Execute($"\"{libref.CsProjPath}\"");
cmd.Should().Pass();
cmd.StdOut.Should().Contain("could not be found");
cmd.StdOut.Should().Be($"Project reference `{libref.CsProjPath}` could not be found.");
lib.CsProjContent().Should().BeEquivalentTo(csprojContetntBefore);
}
@ -262,7 +289,7 @@ namespace Microsoft.DotNet.Cli.Remove.P2P.Tests
.WithProject(lib.CsProjPath)
.Execute($"{FrameworkNet451Arg} \"{libref.CsProjPath}\"");
cmd.Should().Pass();
cmd.StdOut.Should().Contain("could not be found");
cmd.StdOut.Should().Be($"Project reference `{libref.CsProjPath}` could not be found.");
lib.CsProjContent().Should().BeEquivalentTo(csprojContetntBefore);
}
@ -282,7 +309,7 @@ namespace Microsoft.DotNet.Cli.Remove.P2P.Tests
.WithProject(lib.CsProjPath)
.Execute($"\"{librefNoCond.CsProjPath}\"");
cmd.Should().Pass();
cmd.StdOut.Should().MatchRegex("(^|[\r\n])Project reference[^\r\n]*removed.($|[\r\n])");
cmd.StdOut.Should().Be($"Project reference `{Path.Combine(TestSetup.ProjectName, "Lib", setup.LibCsprojName)}` removed.");
var csproj = lib.CsProj();
csproj.NumberOfItemGroupsWithoutCondition().Should().Be(noCondBefore - 1);
csproj.NumberOfProjectReferencesWithIncludeContaining(librefNoCond.Name).Should().Be(0);
@ -307,7 +334,7 @@ namespace Microsoft.DotNet.Cli.Remove.P2P.Tests
.WithProject(lib.CsProjPath)
.Execute($"{FrameworkNet451Arg} \"{librefCond.CsProjPath}\"");
cmd.Should().Pass();
cmd.StdOut.Should().MatchRegex("(^|[\r\n])Project reference[^\r\n]*removed.($|[\r\n])");
cmd.StdOut.Should().Be($"Project reference `{Path.Combine(TestSetup.ProjectName, "Lib", setup.LibCsprojName)}` removed.");
var csproj = lib.CsProj();
csproj.NumberOfItemGroupsWithoutCondition().Should().Be(noCondBefore);
csproj.NumberOfProjectReferencesWithIncludeContaining(librefNoCond.Name).Should().Be(1);
@ -332,7 +359,7 @@ namespace Microsoft.DotNet.Cli.Remove.P2P.Tests
.WithProject(lib.CsProjPath)
.Execute($"{FrameworkNet451Arg} \"{librefCondNet451.CsProjPath}\"");
cmd.Should().Pass();
cmd.StdOut.Should().MatchRegex("(^|[\r\n])Project reference[^\r\n]*removed.($|[\r\n])");
cmd.StdOut.Should().Be($"Project reference `{Path.Combine(TestSetup.ProjectName, "Lib", setup.LibCsprojName)}` removed.");
var csproj = lib.CsProj();
csproj.NumberOfItemGroupsWithConditionContaining(ConditionFrameworkNet451).Should().Be(condNet451Before - 1);
csproj.NumberOfProjectReferencesWithIncludeAndConditionContaining(librefCondNet451.Name, ConditionFrameworkNet451).Should().Be(0);
@ -348,13 +375,16 @@ namespace Microsoft.DotNet.Cli.Remove.P2P.Tests
var proj = new ProjDir(Path.Combine(setup.TestRoot, "WithDoubledRef"));
var libref = GetLibRef(setup);
string removedText = $@"Project reference `{setup.LibCsprojRelPath}` removed.
Project reference `{setup.LibCsprojRelPath}` removed.";
int noCondBefore = proj.CsProj().NumberOfItemGroupsWithoutCondition();
var cmd = new RemoveP2PCommand()
.WithWorkingDirectory(setup.TestRoot)
.WithProject(proj.CsProjPath)
.Execute($"\"{libref.CsProjPath}\"");
cmd.Should().Pass();
cmd.StdOut.Should().MatchRegex("(^|[\r\n])Project reference[^\r\n]*removed.($|[\r\n])");
cmd.StdOut.Should().Be(removedText);
var csproj = proj.CsProj();
csproj.NumberOfItemGroupsWithoutCondition().Should().Be(noCondBefore - 1);
@ -374,7 +404,7 @@ namespace Microsoft.DotNet.Cli.Remove.P2P.Tests
.WithProject(lib.CsProjPath)
.Execute($"\"{setup.ValidRefCsprojRelToOtherProjPath}\"");
cmd.Should().Pass();
cmd.StdOut.Should().MatchRegex("(^|[\r\n])Project reference[^\r\n]*removed.($|[\r\n])");
cmd.StdOut.Should().Be($"Project reference `{setup.ValidRefCsprojRelToOtherProjPath}` removed.");
var csproj = lib.CsProj();
csproj.NumberOfItemGroupsWithoutCondition().Should().Be(noCondBefore - 1);
csproj.NumberOfProjectReferencesWithIncludeContaining(libref.Name).Should().Be(0);
@ -393,7 +423,7 @@ namespace Microsoft.DotNet.Cli.Remove.P2P.Tests
.WithProject(lib.CsProjPath)
.Execute($"\"{setup.ValidRefCsprojRelToOtherProjPath}\"");
cmd.Should().Pass();
cmd.StdOut.Should().MatchRegex("(^|[\r\n])Project reference[^\r\n]*removed.($|[\r\n])");
cmd.StdOut.Should().Be($"Project reference `{setup.ValidRefCsprojRelToOtherProjPath}` removed.");
var csproj = lib.CsProj();
csproj.NumberOfItemGroupsWithoutCondition().Should().Be(noCondBefore - 1);
csproj.NumberOfProjectReferencesWithIncludeContaining(libref.Name).Should().Be(0);
@ -412,7 +442,7 @@ namespace Microsoft.DotNet.Cli.Remove.P2P.Tests
.WithProject(lib.CsProjPath)
.Execute($"\"{setup.ValidRefCsprojPath}\"");
cmd.Should().Pass();
cmd.StdOut.Should().MatchRegex("(^|[\r\n])Project reference[^\r\n]*removed.($|[\r\n])");
cmd.StdOut.Should().Be($"Project reference `{setup.ValidRefCsprojRelToOtherProjPath}` removed.");
var csproj = lib.CsProj();
csproj.NumberOfItemGroupsWithoutCondition().Should().Be(noCondBefore - 1);
csproj.NumberOfProjectReferencesWithIncludeContaining(libref.Name).Should().Be(0);
@ -426,13 +456,16 @@ namespace Microsoft.DotNet.Cli.Remove.P2P.Tests
var libref = AddLibRef(setup, lib);
var validref = AddValidRef(setup, lib);
string outputText = $@"Project reference `{Path.Combine(TestSetup.ProjectName, "Lib", setup.LibCsprojName)}` removed.
Project reference `{Path.Combine(TestSetup.ProjectName, setup.ValidRefCsprojRelPath)}` removed.";
int noCondBefore = lib.CsProj().NumberOfItemGroupsWithoutCondition();
var cmd = new RemoveP2PCommand()
.WithWorkingDirectory(setup.TestRoot)
.WithProject(lib.CsProjPath)
.Execute($"\"{libref.CsProjPath}\" \"{validref.CsProjPath}\"");
cmd.Should().Pass();
cmd.StdOut.Should().MatchRegex("(^|[\r\n])Project reference[^\r\n]*removed.($|[\r\n])");
cmd.StdOut.Should().Be(outputText);
var csproj = lib.CsProj();
csproj.NumberOfItemGroupsWithoutCondition().Should().Be(noCondBefore - 1);
csproj.NumberOfProjectReferencesWithIncludeContaining(libref.Name).Should().Be(0);
@ -447,14 +480,16 @@ namespace Microsoft.DotNet.Cli.Remove.P2P.Tests
var libref = GetLibRef(setup);
var validref = AddValidRef(setup, lib);
string OutputText = $@"Project reference `{setup.LibCsprojPath}` could not be found.
Project reference `{Path.Combine(TestSetup.ProjectName, setup.ValidRefCsprojRelPath)}` removed.";
int noCondBefore = lib.CsProj().NumberOfItemGroupsWithoutCondition();
var cmd = new RemoveP2PCommand()
.WithWorkingDirectory(setup.TestRoot)
.WithProject(lib.CsProjPath)
.Execute($"\"{libref.CsProjPath}\" \"{validref.CsProjPath}\"");
cmd.Should().Pass();
cmd.StdOut.Should().MatchRegex("(^|[\r\n])Project reference[^\r\n]*removed.($|[\r\n])");
cmd.StdOut.Should().Contain("could not be found");
cmd.StdOut.Should().Be(OutputText);
var csproj = lib.CsProj();
csproj.NumberOfItemGroupsWithoutCondition().Should().Be(noCondBefore - 1);
csproj.NumberOfProjectReferencesWithIncludeContaining(validref.Name).Should().Be(0);

View file

@ -0,0 +1,280 @@
// 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 FluentAssertions;
using Microsoft.DotNet.Cli.Sln.Internal;
using Microsoft.DotNet.Tools.Test.Utilities;
using System;
using System.IO;
using Xunit;
namespace Microsoft.DotNet.Cli.Remove.P2P.Tests
{
public class GivenDotnetRemoveProj : TestBase
{
private const string HelpText = @".NET Remove Project from Solution Command
Usage: dotnet remove <PROJECT_OR_SOLUTION> project [options] [args]
Arguments:
<PROJECT_OR_SOLUTION> The project or solution to operation on. If a file is not specified, the current directory is searched.
Options:
-h|--help Show help information
Args:
Projects to remove from a solution
";
[Theory]
[InlineData("--help")]
[InlineData("-h")]
public void WhenHelpOptionIsPassedItPrintsUsage(string helpArg)
{
var cmd = new DotnetCommand()
.ExecuteWithCapturedOutput($"remove project {helpArg}");
cmd.Should().Pass();
cmd.StdOut.Should().Be(HelpText);
}
[Fact]
public void WhenTooManyArgumentsArePassedItPrintsError()
{
var cmd = new DotnetCommand()
.ExecuteWithCapturedOutput("remove one.sln two.sln three.sln project");
cmd.Should().Fail();
cmd.StdErr.Should().Be("Unrecognized command or argument 'two.sln'");
cmd.StdOut.Should().Be("Specify --help for a list of available options and commands.");
}
[Theory]
[InlineData("")]
[InlineData("unknownCommandName")]
public void WhenNoCommandIsPassedItPrintsError(string commandName)
{
var cmd = new DotnetCommand()
.ExecuteWithCapturedOutput($"remove {commandName}");
cmd.Should().Fail();
cmd.StdErr.Should().Be("Required command was not provided.");
}
[Theory]
[InlineData("idontexist.sln")]
[InlineData("ihave?invalidcharacters")]
[InlineData("ihaveinv@lidcharacters")]
[InlineData("ihaveinvalid/characters")]
[InlineData("ihaveinvalidchar\\acters")]
public void WhenNonExistingSolutionIsPassedItPrintsErrorAndUsage(string solutionName)
{
var cmd = new DotnetCommand()
.ExecuteWithCapturedOutput($"remove {solutionName} project p.csproj");
cmd.Should().Fail();
cmd.StdErr.Should().Be($"Could not find solution or directory `{solutionName}`.");
cmd.StdOut.Should().Be(HelpText);
}
[Fact]
public void WhenInvalidSolutionIsPassedItPrintsErrorAndUsage()
{
var projectDirectory = TestAssets
.Get("InvalidSolution")
.CreateInstance()
.WithSourceFiles()
.Root
.FullName;
var projectToRemove = Path.Combine("Lib", "Lib.csproj");
var cmd = new DotnetCommand()
.WithWorkingDirectory(projectDirectory)
.ExecuteWithCapturedOutput($"remove InvalidSolution.sln project {projectToRemove}");
cmd.Should().Fail();
cmd.StdErr.Should().Be("Invalid solution `InvalidSolution.sln`.");
cmd.StdOut.Should().Be(HelpText);
}
[Fact]
public void WhenInvalidSolutionIsFoundItPrintsErrorAndUsage()
{
var projectDirectory = TestAssets
.Get("InvalidSolution")
.CreateInstance()
.WithSourceFiles()
.Root
.FullName;
var solutionPath = Path.Combine(projectDirectory, "InvalidSolution.sln");
var projectToRemove = Path.Combine("Lib", "Lib.csproj");
var cmd = new DotnetCommand()
.WithWorkingDirectory(projectDirectory)
.ExecuteWithCapturedOutput($"remove project {projectToRemove}");
cmd.Should().Fail();
cmd.StdErr.Should().Be($"Invalid solution `{solutionPath}`.");
cmd.StdOut.Should().Be(HelpText);
}
[Fact]
public void WhenNoProjectIsPassedItPrintsErrorAndUsage()
{
var projectDirectory = TestAssets
.Get("TestAppWithSlnAndCsprojFiles")
.CreateInstance()
.WithSourceFiles()
.Root
.FullName;
var cmd = new DotnetCommand()
.WithWorkingDirectory(projectDirectory)
.ExecuteWithCapturedOutput(@"remove App.sln project");
cmd.Should().Fail();
cmd.StdErr.Should().Be("You must specify at least one project to remove.");
cmd.StdOut.Should().Be(HelpText);
}
[Fact]
public void WhenNoSolutionExistsInTheDirectoryItPrintsErrorAndUsage()
{
var projectDirectory = TestAssets
.Get("TestAppWithSlnAndCsprojFiles")
.CreateInstance()
.WithSourceFiles()
.Root
.FullName;
var solutionPath = Path.Combine(projectDirectory, "App");
var cmd = new DotnetCommand()
.WithWorkingDirectory(solutionPath)
.ExecuteWithCapturedOutput(@"remove project App.csproj");
cmd.Should().Fail();
cmd.StdErr.Should().Be($"Specified solution file {solutionPath + Path.DirectorySeparatorChar} does not exist, or there is no solution file in the directory.");
cmd.StdOut.Should().Be(HelpText);
}
[Fact]
public void WhenMoreThanOneSolutionExistsInTheDirectoryItPrintsErrorAndUsage()
{
var projectDirectory = TestAssets
.Get("TestAppWithMultipleSlnFiles")
.CreateInstance()
.WithSourceFiles()
.Root
.FullName;
var projectToRemove = Path.Combine("Lib", "Lib.csproj");
var cmd = new DotnetCommand()
.WithWorkingDirectory(projectDirectory)
.ExecuteWithCapturedOutput($"remove project {projectToRemove}");
cmd.Should().Fail();
cmd.StdErr.Should().Be($"Found more than one solution file in {projectDirectory + Path.DirectorySeparatorChar}. Please specify which one to use.");
cmd.StdOut.Should().Be(HelpText);
}
[Fact]
public void WhenPassedAReferenceNotInSlnItPrintsStatus()
{
var projectDirectory = TestAssets
.Get("TestAppWithSlnAndExistingCsprojReferences")
.CreateInstance()
.WithSourceFiles()
.Root
.FullName;
var solutionPath = Path.Combine(projectDirectory, "App.sln");
var contentBefore = File.ReadAllText(solutionPath);
var cmd = new DotnetCommand()
.WithWorkingDirectory(projectDirectory)
.ExecuteWithCapturedOutput("remove project referenceDoesNotExistInSln.csproj");
cmd.Should().Pass();
cmd.StdOut.Should().Be("Project reference `referenceDoesNotExistInSln.csproj` could not be found.");
File.ReadAllText(solutionPath)
.Should().Be(contentBefore);
}
[Fact]
public void WhenPassedAReferenceItRemovesTheReferenceButNotOtherReferences()
{
var projectDirectory = TestAssets
.Get("TestAppWithSlnAndExistingCsprojReferences")
.CreateInstance()
.WithSourceFiles()
.Root
.FullName;
var solutionPath = Path.Combine(projectDirectory, "App.sln");
SlnFile slnFile = SlnFile.Read(solutionPath);
slnFile.Projects.Count.Should().Be(2);
var projectToRemove = Path.Combine("Lib", "Lib.csproj");
var projectToRemoveNormalized = @"Lib\Lib.csproj";
var cmd = new DotnetCommand()
.WithWorkingDirectory(projectDirectory)
.ExecuteWithCapturedOutput($"remove project {projectToRemove}");
cmd.Should().Pass();
cmd.StdOut.Should().Be($"Project reference `{projectToRemoveNormalized}` removed.");
slnFile = SlnFile.Read(solutionPath);
slnFile.Projects.Count.Should().Be(1);
slnFile.Projects[0].FilePath.Should().Be(@"App\App.csproj");
}
[Fact]
public void WhenDuplicateReferencesArePresentItRemovesThemAll()
{
var projectDirectory = TestAssets
.Get("TestAppWithSlnAndDuplicateProjectReferences")
.CreateInstance()
.WithSourceFiles()
.Root
.FullName;
var solutionPath = Path.Combine(projectDirectory, "App.sln");
SlnFile slnFile = SlnFile.Read(solutionPath);
slnFile.Projects.Count.Should().Be(3);
var projectToRemove = Path.Combine("Lib", "Lib.csproj");
var projectToRemoveNormalized = @"Lib\Lib.csproj";
var cmd = new DotnetCommand()
.WithWorkingDirectory(projectDirectory)
.ExecuteWithCapturedOutput($"remove project {projectToRemove}");
cmd.Should().Pass();
string outputText = $@"Project reference `{projectToRemoveNormalized}` removed.
Project reference `{projectToRemoveNormalized}` removed.";
cmd.StdOut.Should().Be(outputText);
slnFile = SlnFile.Read(solutionPath);
slnFile.Projects.Count.Should().Be(1);
slnFile.Projects[0].FilePath.Should().Be(@"App\App.csproj");
}
[Fact]
public void WhenPassedMultipleReferencesAndOneOfThemDoesNotExistItRemovesTheOneThatExists()
{
var projectDirectory = TestAssets
.Get("TestAppWithSlnAndExistingCsprojReferences")
.CreateInstance()
.WithSourceFiles()
.Root
.FullName;
var solutionPath = Path.Combine(projectDirectory, "App.sln");
SlnFile slnFile = SlnFile.Read(solutionPath);
slnFile.Projects.Count.Should().Be(2);
var projectToRemove = Path.Combine("Lib", "Lib.csproj");
var projectToRemoveNormalized = @"Lib\Lib.csproj";
var cmd = new DotnetCommand()
.WithWorkingDirectory(projectDirectory)
.ExecuteWithCapturedOutput($"remove project idontexist.csproj {projectToRemove} idontexisteither.csproj");
cmd.Should().Pass();
string outputText = $@"Project reference `idontexist.csproj` could not be found.
Project reference `{projectToRemoveNormalized}` removed.
Project reference `idontexisteither.csproj` could not be found.";
cmd.StdOut.Should().Be(outputText);
slnFile = SlnFile.Read(solutionPath);
slnFile.Projects.Count.Should().Be(1);
slnFile.Projects[0].FilePath.Should().Be(@"App\App.csproj");
}
}
}

View file

@ -0,0 +1 @@
https://github.com/Microsoft/msbuild/issues/927

View file

@ -0,0 +1 @@
https://github.com/Microsoft/msbuild/issues/927

View file

@ -0,0 +1,44 @@
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" />
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
<TargetFramework>netcoreapp1.0</TargetFramework>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
<AssemblyName>dotnet-remove-proj.Tests</AssemblyName>
<PackageTargetFallback Condition=" '$(TargetFramework)' == 'netcoreapp1.0' ">$(PackageTargetFallback);dotnet5.4;portable-net451+win8</PackageTargetFallback>
</PropertyGroup>
<ItemGroup>
<Compile Include="**\*.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Microsoft.DotNet.Tools.Tests.Utilities\Microsoft.DotNet.Tools.Tests.Utilities.csproj" />
<ProjectReference Include="..\..\src\Microsoft.DotNet.Cli.Sln.Internal\Microsoft.DotNet.Cli.Sln.Internal.csproj" />
<ProjectReference Include="..\..\src\Microsoft.DotNet.Cli.Utils\Microsoft.DotNet.Cli.Utils.csproj" />
<ProjectReference Include="..\..\src\Microsoft.DotNet.InternalAbstractions\Microsoft.DotNet.InternalAbstractions.csproj" />
<ProjectReference Include="..\..\src\Microsoft.DotNet.TestFramework\Microsoft.DotNet.TestFramework.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Sdk">
<Version>$(CLI_NETSDK_Version)</Version>
<PrivateAssets>All</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk">
<Version>15.0.0-preview-20161024-02</Version>
</PackageReference>
<PackageReference Include="xunit.runner.visualstudio">
<Version>2.2.0-beta4-build1194</Version>
</PackageReference>
<PackageReference Include="Microsoft.NETCore.App">
<Version>1.0.1</Version>
</PackageReference>
<PackageReference Include="xunit">
<Version>2.2.0-beta4-build3444</Version>
</PackageReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>