Lock on spec - all tests passing on Windows
This commit is contained in:
parent
19dde128ba
commit
58fe57e315
4 changed files with 120 additions and 79 deletions
src/dotnet/commands/dotnet-add-p2p
test/dotnet-add-p2p.Tests
|
@ -9,6 +9,7 @@ using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Microsoft.Build.Construction;
|
using Microsoft.Build.Construction;
|
||||||
using Microsoft.Build.Evaluation;
|
using Microsoft.Build.Evaluation;
|
||||||
|
using Microsoft.DotNet.Tools.Common;
|
||||||
|
|
||||||
namespace Microsoft.DotNet.Tools.Add.ProjectToProjectReference
|
namespace Microsoft.DotNet.Tools.Add.ProjectToProjectReference
|
||||||
{
|
{
|
||||||
|
@ -42,18 +43,29 @@ namespace Microsoft.DotNet.Tools.Add.ProjectToProjectReference
|
||||||
|
|
||||||
CommandOption forceOption = app.Option(
|
CommandOption forceOption = app.Option(
|
||||||
"--force",
|
"--force",
|
||||||
"Add reference even if it does not exist",
|
"Add reference even if it does not exist, do not convert paths to relative",
|
||||||
CommandOptionType.NoValue);
|
CommandOptionType.NoValue);
|
||||||
|
|
||||||
app.OnExecute(() => {
|
app.OnExecute(() => {
|
||||||
if (projectArgument.Value == null)
|
if (string.IsNullOrEmpty(projectArgument.Value))
|
||||||
{
|
{
|
||||||
throw new GracefulException("Argument <Project> is required.");
|
throw new GracefulException("Argument <Project> is required.");
|
||||||
}
|
}
|
||||||
|
|
||||||
ProjectRootElement project = File.Exists(projectArgument.Value) ?
|
ProjectRootElement project;
|
||||||
GetProjectFromFileOrThrow(projectArgument.Value) :
|
string projectDir;
|
||||||
GetProjectFromDirectoryOrThrow(projectArgument.Value);
|
if (File.Exists(projectArgument.Value))
|
||||||
|
{
|
||||||
|
project = GetProjectFromFileOrThrow(projectArgument.Value);
|
||||||
|
projectDir = new FileInfo(projectArgument.Value).DirectoryName;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
project = GetProjectFromDirectoryOrThrow(projectArgument.Value);
|
||||||
|
projectDir = projectArgument.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
projectDir = PathUtility.EnsureTrailingSlash(projectDir);
|
||||||
|
|
||||||
if (app.RemainingArguments.Count == 0)
|
if (app.RemainingArguments.Count == 0)
|
||||||
{
|
{
|
||||||
|
@ -63,22 +75,8 @@ namespace Microsoft.DotNet.Tools.Add.ProjectToProjectReference
|
||||||
List<string> references = app.RemainingArguments;
|
List<string> references = app.RemainingArguments;
|
||||||
if (!forceOption.HasValue())
|
if (!forceOption.HasValue())
|
||||||
{
|
{
|
||||||
var notExisting = new List<string>();
|
EnsureAllReferencesExist(references);
|
||||||
foreach (var r in references)
|
ConvertPathsToRelative(projectDir, ref references);
|
||||||
{
|
|
||||||
if (!File.Exists(r))
|
|
||||||
{
|
|
||||||
notExisting.Add(r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (notExisting.Count > 0)
|
|
||||||
{
|
|
||||||
throw new GracefulException(
|
|
||||||
string.Join(
|
|
||||||
Environment.NewLine,
|
|
||||||
notExisting.Select((ne) => $"Reference `{ne}` does not exist.")));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int numberOfAddedReferences = AddProjectToProjectReference(
|
int numberOfAddedReferences = AddProjectToProjectReference(
|
||||||
|
@ -106,6 +104,32 @@ namespace Microsoft.DotNet.Tools.Add.ProjectToProjectReference
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static void EnsureAllReferencesExist(List<string> references)
|
||||||
|
{
|
||||||
|
var notExisting = new List<string>();
|
||||||
|
foreach (var r in references)
|
||||||
|
{
|
||||||
|
if (!File.Exists(r))
|
||||||
|
{
|
||||||
|
notExisting.Add(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notExisting.Count > 0)
|
||||||
|
{
|
||||||
|
throw new GracefulException(
|
||||||
|
string.Join(
|
||||||
|
Environment.NewLine,
|
||||||
|
notExisting.Select((ne) => $"Reference `{ne}` does not exist.")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void ConvertPathsToRelative(string root, ref List<string> references)
|
||||||
|
{
|
||||||
|
root = PathUtility.EnsureTrailingSlash(Path.GetFullPath(root));
|
||||||
|
references = references.Select((r) => PathUtility.GetRelativePath(root, Path.GetFullPath(r))).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
// There is ProjectRootElement.TryOpen but it does not work as expected
|
// There is ProjectRootElement.TryOpen but it does not work as expected
|
||||||
// I.e. it returns null for some valid projects
|
// I.e. it returns null for some valid projects
|
||||||
internal static ProjectRootElement TryOpenProject(string filename)
|
internal static ProjectRootElement TryOpenProject(string filename)
|
||||||
|
@ -181,13 +205,18 @@ namespace Microsoft.DotNet.Tools.Add.ProjectToProjectReference
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string NormalizeSlashesForMsbuild(string path)
|
||||||
|
{
|
||||||
|
return path.Replace('/', '\\');
|
||||||
|
}
|
||||||
|
|
||||||
internal static int AddProjectToProjectReference(ProjectRootElement root, string framework, IEnumerable<string> refs)
|
internal static int AddProjectToProjectReference(ProjectRootElement root, string framework, IEnumerable<string> refs)
|
||||||
{
|
{
|
||||||
int numberOfAddedReferences = 0;
|
int numberOfAddedReferences = 0;
|
||||||
const string ProjectItemElementType = "ProjectReference";
|
const string ProjectItemElementType = "ProjectReference";
|
||||||
|
|
||||||
ProjectItemGroupElement ig = null;
|
ProjectItemGroupElement ig = null;
|
||||||
foreach (var @ref in refs)
|
foreach (var @ref in refs.Select((r) => NormalizeSlashesForMsbuild(r)))
|
||||||
{
|
{
|
||||||
if (root.HasExistingItemWithCondition(framework, @ref))
|
if (root.HasExistingItemWithCondition(framework, @ref))
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,43 +11,6 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
|
||||||
{
|
{
|
||||||
internal static class Extensions
|
internal static class Extensions
|
||||||
{
|
{
|
||||||
//public static int CountOccurrances(this string s, string pattern)
|
|
||||||
//{
|
|
||||||
// int ret = 0;
|
|
||||||
// for (int i = s.IndexOf(pattern); i != -1; i = s.IndexOf(pattern, i + 1))
|
|
||||||
// {
|
|
||||||
// ret++;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return ret;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//public static int NumberOfLinesWith(this string s, params string[] patterns)
|
|
||||||
//{
|
|
||||||
// int ret = 0;
|
|
||||||
// string[] lines = s.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
// foreach (var line in lines)
|
|
||||||
// {
|
|
||||||
// bool shouldCount = true;
|
|
||||||
|
|
||||||
// foreach (var p in patterns)
|
|
||||||
// {
|
|
||||||
// if (!line.Contains(p))
|
|
||||||
// {
|
|
||||||
// shouldCount = false;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (shouldCount)
|
|
||||||
// {
|
|
||||||
// ret++;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return ret;
|
|
||||||
//}
|
|
||||||
|
|
||||||
public static int NumberOfItemGroupsWithConditionContaining(this ProjectRootElement root, string patternInCondition)
|
public static int NumberOfItemGroupsWithConditionContaining(this ProjectRootElement root, string patternInCondition)
|
||||||
{
|
{
|
||||||
return root.ItemGroups.Count((ig) => ig.Condition.Contains(patternInCondition));
|
return root.ItemGroups.Count((ig) => ig.Condition.Contains(patternInCondition));
|
||||||
|
|
|
@ -64,7 +64,6 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
|
||||||
[InlineData("ihave?inv@lid/char\\acters")]
|
[InlineData("ihave?inv@lid/char\\acters")]
|
||||||
public void WhenNonExistingProjectIsPassedItPrintsErrorAndUsage(string projName)
|
public void WhenNonExistingProjectIsPassedItPrintsErrorAndUsage(string projName)
|
||||||
{
|
{
|
||||||
string testRoot = NewDir().Path;
|
|
||||||
var setup = Setup();
|
var setup = Setup();
|
||||||
|
|
||||||
var cmd = new AddP2PCommand()
|
var cmd = new AddP2PCommand()
|
||||||
|
@ -99,7 +98,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
|
||||||
|
|
||||||
var cmd = new AddP2PCommand()
|
var cmd = new AddP2PCommand()
|
||||||
.WithWorkingDirectory(Path.Combine(setup.TestRoot, "MoreThanOne"))
|
.WithWorkingDirectory(Path.Combine(setup.TestRoot, "MoreThanOne"))
|
||||||
.Execute($"\"{setup.ValidRefCsprojRelPath}\"");
|
.Execute($"\"{setup.ValidRefCsprojRelToOtherProjPath}\"");
|
||||||
cmd.ExitCode.Should().NotBe(0);
|
cmd.ExitCode.Should().NotBe(0);
|
||||||
cmd.StdErr.Should().Contain("more than one");
|
cmd.StdErr.Should().Contain("more than one");
|
||||||
cmd.StdOut.Should().Contain("Usage");
|
cmd.StdOut.Should().Contain("Usage");
|
||||||
|
@ -550,28 +549,80 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
|
||||||
lib.CsProjContent().Should().BeEquivalentTo(contentBefore);
|
lib.CsProjContent().Should().BeEquivalentTo(contentBefore);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Skip = "Not finished")]
|
[Fact]
|
||||||
public void WhenPassedReferenceDoesNotExistAndForceSwitchIsPassedItAddsIt()
|
public void WhenPassedReferenceDoesNotExistAndForceSwitchIsPassedItAddsIt()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
var lib = NewLib();
|
||||||
|
const string nonExisting = "IDoNotExist.csproj";
|
||||||
|
|
||||||
|
int noCondBefore = lib.CsProj().NumberOfItemGroupsWithoutCondition();
|
||||||
|
var cmd = new AddP2PCommand()
|
||||||
|
.WithWorkingDirectory(lib.Path)
|
||||||
|
.WithProject(lib.CsProjName)
|
||||||
|
.Execute($"--force \"{nonExisting}\"");
|
||||||
|
cmd.Should().Pass();
|
||||||
|
cmd.StdOut.Should().Contain("added to the project");
|
||||||
|
cmd.StdErr.Should().BeEmpty();
|
||||||
|
var csproj = lib.CsProj();
|
||||||
|
csproj.NumberOfItemGroupsWithoutCondition().Should().Be(noCondBefore + 1);
|
||||||
|
csproj.NumberOfProjectReferencesWithIncludeContaining(nonExisting).Should().Be(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Skip = "Not finished")]
|
[Fact]
|
||||||
public void WhenPassedReferenceIsUsingSlashesItNormalizesItToBackslashes()
|
public void WhenPassedReferenceIsUsingSlashesItNormalizesItToBackslashes()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
var lib = NewLib();
|
||||||
|
var setup = Setup();
|
||||||
|
|
||||||
|
int noCondBefore = lib.CsProj().NumberOfItemGroupsWithoutCondition();
|
||||||
|
var cmd = new AddP2PCommand()
|
||||||
|
.WithWorkingDirectory(lib.Path)
|
||||||
|
.WithProject(lib.CsProjName)
|
||||||
|
.Execute($"--force \"{setup.ValidRefCsprojPath.Replace('\\', '/')}\"");
|
||||||
|
cmd.Should().Pass();
|
||||||
|
cmd.StdOut.Should().Contain("added to the project");
|
||||||
|
cmd.StdErr.Should().BeEmpty();
|
||||||
|
var csproj = lib.CsProj();
|
||||||
|
csproj.NumberOfItemGroupsWithoutCondition().Should().Be(noCondBefore + 1);
|
||||||
|
csproj.NumberOfProjectReferencesWithIncludeContaining(setup.ValidRefCsprojPath.Replace('/', '\\')).Should().Be(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Skip = "Not finished")]
|
[Fact]
|
||||||
public void WhenPassedRefIsUsingBackslashesItDoesntNormalizeIt()
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact(Skip = "Not finished")]
|
|
||||||
public void WhenReferenceIsRelativeAndProjectIsNotInCurrentDirectoryReferencePathIsFixed()
|
public void WhenReferenceIsRelativeAndProjectIsNotInCurrentDirectoryReferencePathIsFixed()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
var setup = Setup();
|
||||||
|
var proj = new ProjDir(setup.LibDir);
|
||||||
|
|
||||||
|
int noCondBefore = proj.CsProj().NumberOfItemGroupsWithoutCondition();
|
||||||
|
var cmd = new AddP2PCommand()
|
||||||
|
.WithWorkingDirectory(setup.TestRoot)
|
||||||
|
.WithProject(setup.LibCsprojPath)
|
||||||
|
.Execute($"\"{setup.ValidRefCsprojRelPath}\"");
|
||||||
|
cmd.Should().Pass();
|
||||||
|
cmd.StdOut.Should().Contain("added to the project");
|
||||||
|
cmd.StdErr.Should().BeEmpty();
|
||||||
|
var csproj = proj.CsProj();
|
||||||
|
csproj.NumberOfItemGroupsWithoutCondition().Should().Be(noCondBefore + 1);
|
||||||
|
csproj.NumberOfProjectReferencesWithIncludeContaining(setup.ValidRefCsprojRelToOtherProjPath).Should().Be(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WhenReferenceIsRelativeAndProjectIsNotInCurrentDirectoryAndForceSwitchIsPassedItDoesNotChangeIt()
|
||||||
|
{
|
||||||
|
var setup = Setup();
|
||||||
|
var proj = new ProjDir(setup.LibDir);
|
||||||
|
|
||||||
|
int noCondBefore = proj.CsProj().NumberOfItemGroupsWithoutCondition();
|
||||||
|
var cmd = new AddP2PCommand()
|
||||||
|
.WithWorkingDirectory(setup.TestRoot)
|
||||||
|
.WithProject(setup.LibCsprojPath)
|
||||||
|
.Execute($"--force \"{setup.ValidRefCsprojRelPath}\"");
|
||||||
|
cmd.Should().Pass();
|
||||||
|
cmd.StdOut.Should().Contain("added to the project");
|
||||||
|
cmd.StdErr.Should().BeEmpty();
|
||||||
|
var csproj = proj.CsProj();
|
||||||
|
csproj.NumberOfItemGroupsWithoutCondition().Should().Be(noCondBefore + 1);
|
||||||
|
csproj.NumberOfProjectReferencesWithIncludeContaining(setup.ValidRefCsprojRelPath).Should().Be(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -14,20 +14,18 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
|
||||||
|
|
||||||
public string TestRoot { get; private set; }
|
public string TestRoot { get; private set; }
|
||||||
|
|
||||||
|
|
||||||
private const string ValidRef = "ValidRef";
|
private const string ValidRef = "ValidRef";
|
||||||
public string ValidRefCsprojName => $"{ValidRef}.csproj";
|
public string ValidRefCsprojName => $"{ValidRef}.csproj";
|
||||||
public string ValidRefCsprojPath => Path.Combine(TestRoot, ValidRef, ValidRefCsprojName);
|
public string ValidRefCsprojRelPath => Path.Combine(ValidRef, ValidRefCsprojName);
|
||||||
public string ValidRefCsprojRelPath => Path.Combine("..", ValidRef, ValidRefCsprojName);
|
public string ValidRefCsprojPath => Path.Combine(TestRoot, ValidRefCsprojRelPath);
|
||||||
|
public string ValidRefCsprojRelToOtherProjPath => Path.Combine("..", ValidRefCsprojRelPath);
|
||||||
|
|
||||||
private const string Lib = "Lib";
|
private const string Lib = "Lib";
|
||||||
|
public string LibDir => Path.Combine(TestRoot, Lib);
|
||||||
public string LibCsprojName => $"{Lib}.csproj";
|
public string LibCsprojName => $"{Lib}.csproj";
|
||||||
public string LibCsprojPath => Path.Combine(TestRoot, Lib, LibCsprojName);
|
public string LibCsprojPath => Path.Combine(TestRoot, Lib, LibCsprojName);
|
||||||
public string LibCsprojRelPath => Path.Combine("..", Lib, LibCsprojName);
|
public string LibCsprojRelPath => Path.Combine("..", Lib, LibCsprojName);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public TestSetup(string testRoot)
|
public TestSetup(string testRoot)
|
||||||
{
|
{
|
||||||
TestRoot = testRoot;
|
TestRoot = testRoot;
|
||||||
|
|
Loading…
Add table
Reference in a new issue