[xharness] Improve project cloning to take into account default inclusion behavior for .NET projects.

.NET projects will include files from the current directory by default, which
means that if we clone the project file and write the cloned project file in a
different directory, we'll have to add an automatically included files into
the cloned file manually.
This commit is contained in:
Rolf Bjarne Kvinge 2020-06-19 14:42:46 +02:00
Родитель 1b703c5fdd
Коммит 5d257bfb8f
4 изменённых файлов: 71 добавлений и 5 удалений

Просмотреть файл

@ -57,6 +57,7 @@ namespace Microsoft.DotNet.XHarness.iOS.Shared.Tasks {
Stopwatch DurationStopWatch { get; }
IEnumerable<string> ReferencedNunitAndXunitTestAssemblies { get; }
string ProgressMessage { get; }
string RootDirectory { get; }
Task RunAsync ();

Просмотреть файл

@ -252,7 +252,7 @@ namespace Microsoft.DotNet.XHarness.iOS.Shared.Tasks {
// So we clone the project file to a separate directory and build there instead.
// This is done asynchronously to speed to the initial test load.
TestProject = project.Clone ();
InitialTask = TestProject.CreateCopyAsync (log, processManager);
InitialTask = TestProject.CreateCopyAsync (log, processManager, this);
}
protected Stopwatch waitingDuration = new Stopwatch ();

Просмотреть файл

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using System.Xml;
@ -71,7 +72,7 @@ namespace Microsoft.DotNet.XHarness.iOS.Shared {
return rv;
}
public async Task CreateCopyAsync (ILog log, IProcessManager processManager, ITestTask test = null)
public async Task CreateCopyAsync (ILog log, IProcessManager processManager, ITestTask test)
{
var directory = DirectoryUtilities.CreateTemporaryDirectory (test?.TestName ?? System.IO.Path.GetFileNameWithoutExtension (Path));
Directory.CreateDirectory (directory);
@ -93,6 +94,65 @@ namespace Microsoft.DotNet.XHarness.iOS.Shared {
}
doc.ResolveAllPaths (original_path);
if (doc.IsDotNetProject ()) {
// Many types of files below the csproj directory are included by default,
// which means that we have to include them manually in the cloned csproj,
// because the cloned project is stored in a very different directory.
var test_dir = System.IO.Path.GetDirectoryName (original_path);
// Get all the files in the project directory from git
using var process = new Process ();
process.StartInfo.FileName = "git";
process.StartInfo.Arguments = "ls-files";
process.StartInfo.WorkingDirectory = test_dir;
var stdout = new MemoryLog () { Timestamp = false };
var result = await processManager.RunAsync (process, log, stdout, stdout, timeout: TimeSpan.FromSeconds (15));
if (!result.Succeeded)
throw new Exception ($"Failed to list the files in the directory {test_dir} (TimedOut: {result.TimedOut} ExitCode: {result.ExitCode}):\n{stdout}");
var files = stdout.ToString ().Split ('\n');
foreach (var file in files) {
var ext = System.IO.Path.GetExtension (file);
var full_path = System.IO.Path.Combine (test_dir, file);
var windows_file = full_path.Replace ('/', '\\');
if (file.Contains (".xcasset")) {
doc.AddInclude ("ImageAsset", file, windows_file, true);
continue;
}
switch (ext.ToLowerInvariant ()) {
case ".cs":
doc.AddInclude ("Compile", file, windows_file, true);
break;
case ".plist":
doc.AddInclude ("None", file, windows_file, true);
break;
case ".storyboard":
doc.AddInclude ("InterfaceDefinition", file, windows_file, true);
break;
case ".gitignore":
case ".csproj":
case ".props": // Directory.Build.props
case "": // Makefile
break; // ignore these files
default:
Console.WriteLine ($"Unknown file: {file} (extension: {ext}). There might be a default inclusion behavior for this file.");
break;
}
}
// The global.json and NuGet.config files make sure we use the locally built packages.
var dotnet_test_dir = System.IO.Path.Combine (test.RootDirectory, "dotnet");
var global_json = System.IO.Path.Combine (dotnet_test_dir, "global.json");
var nuget_config = System.IO.Path.Combine (dotnet_test_dir, "NuGet.config");
var target_directory = directory;
File.Copy (global_json, System.IO.Path.Combine (target_directory, System.IO.Path.GetFileName (global_json)), true);
log.WriteLine ($"Copied {global_json} to {target_directory}");
File.Copy (nuget_config, System.IO.Path.Combine (target_directory, System.IO.Path.GetFileName (nuget_config)), true);
log.WriteLine ($"Copied {nuget_config} to {target_directory}");
}
var projectReferences = new List<TestProject> ();
foreach (var pr in doc.GetProjectReferences ()) {
var tp = new TestProject (pr.Replace ('\\', '/'));

Просмотреть файл

@ -262,10 +262,15 @@ namespace Microsoft.DotNet.XHarness.iOS.Shared.Utilities {
public static void AddCompileInclude (this XmlDocument csproj, string link, string include, bool prepend = false)
{
var compile_node = csproj.SelectSingleNode ("//*[local-name() = 'Compile']");
var item_group = compile_node.ParentNode;
AddInclude (csproj, "Compile", link, include, prepend);
}
var node = csproj.CreateElement ("Compile", csproj.GetNamespace ());
public static void AddInclude (this XmlDocument csproj, string type, string link, string include, bool prepend = false)
{
var type_node = csproj.SelectSingleNode ($"//*[local-name() = '{type}']");
var item_group = type_node?.ParentNode ?? csproj.SelectSingleNode ($"//*[local-name() = 'ItemGroup'][last()]");
var node = csproj.CreateElement (type, csproj.GetNamespace ());
var include_attribute = csproj.CreateAttribute ("Include");
include_attribute.Value = include;
node.Attributes.Append (include_attribute);