public async Task CreateCopyAsync(ILog log, IProcessManager processManager, ITestTask test) { var directory = DirectoryUtilities.CreateTemporaryDirectory(test?.TestName ?? System.IO.Path.GetFileNameWithoutExtension(Path)); Directory.CreateDirectory(directory); var original_path = Path; Path = System.IO.Path.Combine(directory, System.IO.Path.GetFileName(Path)); await Task.Yield(); XmlDocument doc; doc = new XmlDocument(); doc.LoadWithoutNetworkAccess(original_path); var original_name = System.IO.Path.GetFileName(original_path); if (original_name.Contains("GuiUnit_NET") || original_name.Contains("GuiUnit_xammac_mobile")) { // The GuiUnit project files writes stuff outside their project directory using relative paths, // but override that so that we don't end up with multiple cloned projects writing stuff to // the same location. doc.SetOutputPath("bin\\$(Configuration)"); doc.SetNode("DocumentationFile", "bin\\$(Configuration)\\nunitlite.xml"); } 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('\\', '/')); await tp.CreateCopyAsync(log, processManager, test); doc.SetProjectReferenceInclude(pr, tp.Path.Replace('/', '\\')); projectReferences.Add(tp); } this.ProjectReferences = projectReferences; doc.Save(Path); }