From 4952a819d402f0efb5e79f8f5a59c96c4581d322 Mon Sep 17 00:00:00 2001 From: Krzysztof Wicher Date: Fri, 10 Feb 2017 09:49:21 -0800 Subject: [PATCH 1/5] wip --- .../TestAssetInfo.cs | 260 ++++++++++++------ 1 file changed, 179 insertions(+), 81 deletions(-) diff --git a/src/Microsoft.DotNet.TestFramework/TestAssetInfo.cs b/src/Microsoft.DotNet.TestFramework/TestAssetInfo.cs index 760c33ec4..ec272e829 100644 --- a/src/Microsoft.DotNet.TestFramework/TestAssetInfo.cs +++ b/src/Microsoft.DotNet.TestFramework/TestAssetInfo.cs @@ -11,6 +11,8 @@ using System.Threading.Tasks; using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.PlatformAbstractions; using NuGet.Common; +using PathUtility = Microsoft.DotNet.Tools.Common.PathUtility; +using System.Xml.Linq; namespace Microsoft.DotNet.TestFramework { @@ -28,6 +30,8 @@ namespace Microsoft.DotNet.TestFramework private readonly DirectoryInfo _root; + private readonly DirectoryInfo _operationDirectory; + private readonly TestAssetInventoryFiles _inventoryFiles; private readonly FileInfo _dotnetExeFile; @@ -38,7 +42,7 @@ namespace Microsoft.DotNet.TestFramework { get { - return _root; + return _operationDirectory; } } @@ -74,12 +78,16 @@ namespace Microsoft.DotNet.TestFramework _dataDirectory = _root.GetDirectory(DataDirectoryName); + _operationDirectory = _dataDirectory.GetDirectory("files"); + _inventoryFiles = new TestAssetInventoryFiles(_dataDirectory); _directoriesToExclude = new [] { _dataDirectory }; + + //throw new Exception($"root = {_root}\nassetName = {_assetName}\ndotnetExeFile = {_dotnetExeFile}\nprojectFilePattern = {_projectFilePattern}\ndataDir = {_dataDirectory}\ndirectoriesToExclude = {string.Join(";",_directoriesToExclude)}"); } public TestAssetInstance CreateInstance([CallerMemberName] string callingMethod = "", string identifier = "") @@ -95,19 +103,19 @@ namespace Microsoft.DotNet.TestFramework { ThrowIfTestAssetDoesNotExist(); - ThrowIfAssetSourcesHaveChanged(); + RemoveCacheIfSourcesHaveChanged(); return GetInventory( - _inventoryFiles.Source, - null, - () => {}); + _inventoryFiles.Source, + null, + DoCopyFiles); } internal IEnumerable GetRestoreFiles() { ThrowIfTestAssetDoesNotExist(); - ThrowIfAssetSourcesHaveChanged(); + RemoveCacheIfSourcesHaveChanged(); return GetInventory( _inventoryFiles.Restore, @@ -119,12 +127,12 @@ namespace Microsoft.DotNet.TestFramework { ThrowIfTestAssetDoesNotExist(); - ThrowIfAssetSourcesHaveChanged(); + RemoveCacheIfSourcesHaveChanged(); return GetInventory( _inventoryFiles.Build, () => GetRestoreFiles() - .Concat(GetSourceFiles()), + .Concat(GetSourceFiles()), // TODO: likely not needed DoBuild); } @@ -138,7 +146,12 @@ namespace Microsoft.DotNet.TestFramework return new DirectoryInfo(Path.Combine(baseDirectory, callingMethod + identifier, _assetName)); } - private IEnumerable GetFileList() + private IEnumerable GetOperationFileList() + { + return _operationDirectory.GetFiles("*.*", SearchOption.AllDirectories); + } + + private IEnumerable GetOriginalFileList() { return _root.GetFiles("*.*", SearchOption.AllDirectories) .Where(f => !_directoriesToExclude.Any(d => d.Contains(f))) @@ -173,7 +186,7 @@ namespace Microsoft.DotNet.TestFramework { action(); - inventory = GetFileList().Where(i => !preInventory.Select(p => p.FullName).Contains(i.FullName)); + inventory = GetOperationFileList().Where(i => !preInventory.Select(p => p.FullName).Contains(i.FullName)); folder.SaveInventory(file, inventory); } @@ -182,34 +195,136 @@ namespace Microsoft.DotNet.TestFramework return inventory; } + private static string RebasePath(string path, string oldBaseDirectory, string newBaseDirectory) + { + path = Path.IsPathRooted(path) ? PathUtility.GetRelativePath(PathUtility.EnsureTrailingSlash(oldBaseDirectory), path) : path; + return Path.Combine(newBaseDirectory, path); + } + + private void RemoveOperationFiles() + { + foreach (var opFile in GetOperationFileList()) + { + opFile.Delete(); + } + + foreach (var f in _inventoryFiles.AllInventoryFiles) + { + f.Delete(); + } + } + + private bool IsAncestor(FileInfo file, DirectoryInfo maybeAncestor) + { + var dir = file.Directory; + do + { + if (string.Equals(maybeAncestor.FullName, dir.FullName, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + + dir = dir.Parent; + } + while (dir != null); + + return false; + } + + private void DoCopyFiles() + { + Console.WriteLine($"TestAsset CopyFiles '{_assetName}'"); + + _operationDirectory.Refresh(); + if (!_operationDirectory.Exists) + { + _operationDirectory.Create(); + } + else + { + if (_operationDirectory.GetFiles().Any()) + { + throw new Exception("operation files folder not empty"); + } + } + + foreach (var f in GetOriginalFileList()) + { + string destinationPath = RebasePath(f.FullName, _root.FullName, _operationDirectory.FullName); + var destinationDir = new FileInfo(destinationPath).Directory; + if (!destinationDir.Exists) + { + destinationDir.Create(); + } + if (string.Equals(f.Name, "nuget.config", StringComparison.OrdinalIgnoreCase)) + { + var doc = XDocument.Load(f.FullName, LoadOptions.PreserveWhitespace); + foreach (var v in doc.Root.Element("packageSources").Elements("add").Attributes("value")) + { + if (!Path.IsPathRooted(v.Value)) + { + string fullPath = Path.GetFullPath(Path.Combine(f.Directory.FullName, v.Value)); + if (!IsAncestor(new FileInfo(fullPath), _root)) + { + v.Value = fullPath; + } + } + + //throw new Exception($"\nvalue = {v.Value}\n" + + // $"f.dir = {f.Directory.FullName}\n" + + // $"fullPath = {fullPath}"); + + } + + using (var file = new FileStream(destinationPath, FileMode.CreateNew, FileAccess.ReadWrite)) + { + doc.Save(file, SaveOptions.None); + } + } + else + { + f.CopyTo(destinationPath); + } + } + } + private void DoRestore() { - Console.WriteLine($"TestAsset Restore '{_assetName}'"); - - var projFiles = _root.GetFiles(_projectFilePattern, SearchOption.AllDirectories); - - foreach (var projFile in projFiles) + //throw new Exception("foooooo"); + try { - var restoreArgs = new string[] { "restore", projFile.FullName }; + Console.WriteLine($"TestAsset Restore '{_assetName}'"); - var commandResult = Command.Create(_dotnetExeFile.FullName, restoreArgs) - .CaptureStdOut() - .CaptureStdErr() - .Execute(); + _operationDirectory.Refresh(); + var projFiles = _operationDirectory.GetFiles(_projectFilePattern, SearchOption.AllDirectories); - int exitCode = commandResult.ExitCode; - - if (exitCode != 0) + foreach (var projFile in projFiles) { - Console.WriteLine(commandResult.StdOut); + var restoreArgs = new string[] { "restore", projFile.FullName }; - Console.WriteLine(commandResult.StdErr); + var commandResult = Command.Create(_dotnetExeFile.FullName, restoreArgs) + .CaptureStdOut() + .CaptureStdErr() + .Execute(); - string message = string.Format($"TestAsset Restore '{_assetName}'@'{projFile.FullName}' Failed with {exitCode}"); + int exitCode = commandResult.ExitCode; - throw new Exception(message); + if (exitCode != 0) + { + Console.WriteLine(commandResult.StdOut); + + Console.WriteLine(commandResult.StdErr); + + string message = string.Format($"TestAsset Restore '{_assetName}'@'{projFile.FullName}' Failed with {exitCode}"); + + throw new Exception($"TestAsset {_dotnetExeFile.FullName} {string.Join(" ", restoreArgs)}"); + } } } + catch (Exception e) + { + throw new Exception($"NOOOOOOOOOOOOOOOOOOOOOOOOOOOOO:\n{e.Message}"); + } } private void DoBuild() @@ -219,7 +334,7 @@ namespace Microsoft.DotNet.TestFramework Console.WriteLine($"TestAsset Build '{_assetName}'"); var commandResult = Command.Create(_dotnetExeFile.FullName, args) - .WorkingDirectory(_root.FullName) + .WorkingDirectory(_operationDirectory.FullName) .CaptureStdOut() .CaptureStdErr() .Execute(); @@ -238,68 +353,51 @@ namespace Microsoft.DotNet.TestFramework } } - private void ThrowIfAssetSourcesHaveChanged() + private bool HaveSourcesChanged(ExclusiveFolderAccess folder) { - if (!_dataDirectory.Exists) + var originalFiles = GetOriginalFileList(); + var originalFilesRebased = originalFiles.Select(f => RebasePath(f.FullName, _root.FullName, _operationDirectory.FullName)); + var trackedOriginalFiles = folder.LoadInventory(_inventoryFiles.Source); + + bool hasUntrackedFiles = originalFilesRebased.Any(a => !trackedOriginalFiles.Any(t => t.FullName.Equals(a))); + if (hasUntrackedFiles) { - return; + return true; } - var dataDirectoryFiles = _dataDirectory.GetFiles("*", SearchOption.AllDirectories); - - if (!dataDirectoryFiles.Any()) + bool hasMissingFiles = trackedOriginalFiles.Any(t => !File.Exists(RebasePath(t.FullName, _operationDirectory.FullName, _root.FullName))); + if (hasMissingFiles) { - return; + return true; } - IEnumerable trackedFiles = null; + foreach (var origFile in originalFiles) + { + var copiedFile = new FileInfo(RebasePath(origFile.FullName, _root.FullName, _operationDirectory.FullName)); + if (origFile.LastWriteTimeUtc != copiedFile.LastWriteTimeUtc) + { + return true; + } + } + + return false; + } + + private void RemoveCacheIfSourcesHaveChanged() + { ExclusiveFolderAccess.Do(_dataDirectory, (folder) => { - trackedFiles = _inventoryFiles.AllInventoryFiles.SelectMany(f => folder.LoadInventory(f)); + _operationDirectory.Refresh(); + if (!_operationDirectory.Exists) + { + return; + } + + if (HaveSourcesChanged(folder)) + { + Console.WriteLine("Sources have changed................................"); + RemoveOperationFiles(); + } }); - - var assetFiles = GetFileList(); - - var untrackedFiles = assetFiles.Where(a => !trackedFiles.Any(t => t.FullName.Equals(a.FullName))); - - if (untrackedFiles.Any()) - { - var message = $"TestAsset {_assetName} has untracked files. " + - "Consider cleaning the asset and deleting its `.tam` directory to " + - "recreate tracking files.\n\n" + - $".tam directory: {_dataDirectory.FullName}\n" + - "Untracked Files: \n"; - - message += String.Join("\n", untrackedFiles.Select(f => $" - {f.FullName}\n")); - - throw new Exception(message); - } - - var earliestDataDirectoryTimestamp = - dataDirectoryFiles - .OrderBy(f => f.LastWriteTime) - .First() - .LastWriteTime; - - if (earliestDataDirectoryTimestamp == null) - { - return; - } - - var updatedSourceFiles = ExclusiveFolderAccess.Read(_inventoryFiles.Source) - .Where(f => f.LastWriteTime > earliestDataDirectoryTimestamp); - - if (updatedSourceFiles.Any()) - { - var message = $"TestAsset {_assetName} has updated files. " + - "Consider cleaning the asset and deleting its `.tam` directory to " + - "recreate tracking files.\n\n" + - $".tam directory: {_dataDirectory.FullName}\n" + - "Updated Files: \n"; - - message += String.Join("\n", updatedSourceFiles.Select(f => $" - {f.FullName}\n")); - - throw new GracefulException(message); - } } private void ThrowIfTestAssetDoesNotExist() From f77c5d76cbf482cf1198c8eb37a0da7e8f99554b Mon Sep 17 00:00:00 2001 From: Krzysztof Wicher Date: Fri, 10 Feb 2017 10:54:05 -0800 Subject: [PATCH 2/5] copy files and direct restore and build without adjusting paths --- .../TestAssetInfo.cs | 419 +++--------------- .../TestAssetInstance.cs | 110 ++++- 2 files changed, 161 insertions(+), 368 deletions(-) diff --git a/src/Microsoft.DotNet.TestFramework/TestAssetInfo.cs b/src/Microsoft.DotNet.TestFramework/TestAssetInfo.cs index ec272e829..c8502ec63 100644 --- a/src/Microsoft.DotNet.TestFramework/TestAssetInfo.cs +++ b/src/Microsoft.DotNet.TestFramework/TestAssetInfo.cs @@ -18,33 +18,15 @@ namespace Microsoft.DotNet.TestFramework { public class TestAssetInfo { - private const string DataDirectoryName = ".tam"; - private readonly string [] FilesToExclude = { ".DS_Store", ".noautobuild" }; - private readonly DirectoryInfo [] _directoriesToExclude; + public string AssetName { get; private set; } - private readonly string _assetName; + public FileInfo DotnetExeFile { get; private set; } - private readonly DirectoryInfo _dataDirectory; + public string ProjectFilePattern { get; private set; } - private readonly DirectoryInfo _root; - - private readonly DirectoryInfo _operationDirectory; - - private readonly TestAssetInventoryFiles _inventoryFiles; - - private readonly FileInfo _dotnetExeFile; - - private readonly string _projectFilePattern; - - internal DirectoryInfo Root - { - get - { - return _operationDirectory; - } - } + public DirectoryInfo Root { get; private set; } internal TestAssetInfo(DirectoryInfo root, string assetName, FileInfo dotnetExeFile, string projectFilePattern) { @@ -68,24 +50,13 @@ namespace Microsoft.DotNet.TestFramework throw new ArgumentException("Argument cannot be null or whitespace", nameof(projectFilePattern)); } - _root = root; + Root = root; - _assetName = assetName; + AssetName = assetName; - _dotnetExeFile = dotnetExeFile; + DotnetExeFile = dotnetExeFile; - _projectFilePattern = projectFilePattern; - - _dataDirectory = _root.GetDirectory(DataDirectoryName); - - _operationDirectory = _dataDirectory.GetDirectory("files"); - - _inventoryFiles = new TestAssetInventoryFiles(_dataDirectory); - - _directoriesToExclude = new [] - { - _dataDirectory - }; + ProjectFilePattern = projectFilePattern; //throw new Exception($"root = {_root}\nassetName = {_assetName}\ndotnetExeFile = {_dotnetExeFile}\nprojectFilePattern = {_projectFilePattern}\ndataDir = {_dataDirectory}\ndirectoriesToExclude = {string.Join(";",_directoriesToExclude)}"); } @@ -103,37 +74,8 @@ namespace Microsoft.DotNet.TestFramework { ThrowIfTestAssetDoesNotExist(); - RemoveCacheIfSourcesHaveChanged(); - - return GetInventory( - _inventoryFiles.Source, - null, - DoCopyFiles); - } - - internal IEnumerable GetRestoreFiles() - { - ThrowIfTestAssetDoesNotExist(); - - RemoveCacheIfSourcesHaveChanged(); - - return GetInventory( - _inventoryFiles.Restore, - GetSourceFiles, - DoRestore); - } - - internal IEnumerable GetBuildFiles() - { - ThrowIfTestAssetDoesNotExist(); - - RemoveCacheIfSourcesHaveChanged(); - - return GetInventory( - _inventoryFiles.Build, - () => GetRestoreFiles() - .Concat(GetSourceFiles()), // TODO: likely not needed - DoBuild); + return Root.GetFiles("*.*", SearchOption.AllDirectories) + .Where(f => !FilesToExclude.Contains(f.Name)); } private DirectoryInfo GetTestDestinationDirectory(string callingMethod, string identifier) @@ -143,56 +85,7 @@ namespace Microsoft.DotNet.TestFramework #else string baseDirectory = AppContext.BaseDirectory; #endif - return new DirectoryInfo(Path.Combine(baseDirectory, callingMethod + identifier, _assetName)); - } - - private IEnumerable GetOperationFileList() - { - return _operationDirectory.GetFiles("*.*", SearchOption.AllDirectories); - } - - private IEnumerable GetOriginalFileList() - { - return _root.GetFiles("*.*", SearchOption.AllDirectories) - .Where(f => !_directoriesToExclude.Any(d => d.Contains(f))) - .Where(f => !FilesToExclude.Contains(f.Name)); - } - - private IEnumerable GetInventory( - FileInfo file, - Func> beforeAction, - Action action) - { - var inventory = Enumerable.Empty(); - - IEnumerable preInventory; - - if (beforeAction == null) - { - preInventory = new List(); - } - else - { - preInventory = beforeAction(); - } - - ExclusiveFolderAccess.Do(_dataDirectory, (folder) => { - file.Refresh(); - if (file.Exists) - { - inventory = folder.LoadInventory(file); - } - else - { - action(); - - inventory = GetOperationFileList().Where(i => !preInventory.Select(p => p.FullName).Contains(i.FullName)); - - folder.SaveInventory(file, inventory); - } - }); - - return inventory; + return new DirectoryInfo(Path.Combine(baseDirectory, callingMethod + identifier, AssetName)); } private static string RebasePath(string path, string oldBaseDirectory, string newBaseDirectory) @@ -201,19 +94,6 @@ namespace Microsoft.DotNet.TestFramework return Path.Combine(newBaseDirectory, path); } - private void RemoveOperationFiles() - { - foreach (var opFile in GetOperationFileList()) - { - opFile.Delete(); - } - - foreach (var f in _inventoryFiles.AllInventoryFiles) - { - f.Delete(); - } - } - private bool IsAncestor(FileInfo file, DirectoryInfo maybeAncestor) { var dir = file.Directory; @@ -231,241 +111,70 @@ namespace Microsoft.DotNet.TestFramework return false; } - private void DoCopyFiles() - { - Console.WriteLine($"TestAsset CopyFiles '{_assetName}'"); + //private void DoCopyFiles() + //{ + // Console.WriteLine($"TestAsset CopyFiles '{AssetName}'"); - _operationDirectory.Refresh(); - if (!_operationDirectory.Exists) - { - _operationDirectory.Create(); - } - else - { - if (_operationDirectory.GetFiles().Any()) - { - throw new Exception("operation files folder not empty"); - } - } + // _operationDirectory.Refresh(); + // if (!_operationDirectory.Exists) + // { + // _operationDirectory.Create(); + // } + // else + // { + // if (_operationDirectory.GetFiles().Any()) + // { + // throw new Exception("operation files folder not empty"); + // } + // } - foreach (var f in GetOriginalFileList()) - { - string destinationPath = RebasePath(f.FullName, _root.FullName, _operationDirectory.FullName); - var destinationDir = new FileInfo(destinationPath).Directory; - if (!destinationDir.Exists) - { - destinationDir.Create(); - } - if (string.Equals(f.Name, "nuget.config", StringComparison.OrdinalIgnoreCase)) - { - var doc = XDocument.Load(f.FullName, LoadOptions.PreserveWhitespace); - foreach (var v in doc.Root.Element("packageSources").Elements("add").Attributes("value")) - { - if (!Path.IsPathRooted(v.Value)) - { - string fullPath = Path.GetFullPath(Path.Combine(f.Directory.FullName, v.Value)); - if (!IsAncestor(new FileInfo(fullPath), _root)) - { - v.Value = fullPath; - } - } + // foreach (var f in GetOriginalFileList()) + // { + // string destinationPath = RebasePath(f.FullName, Root.FullName, _operationDirectory.FullName); + // var destinationDir = new FileInfo(destinationPath).Directory; + // if (!destinationDir.Exists) + // { + // destinationDir.Create(); + // } + // if (string.Equals(f.Name, "nuget.config", StringComparison.OrdinalIgnoreCase)) + // { + // var doc = XDocument.Load(f.FullName, LoadOptions.PreserveWhitespace); + // foreach (var v in doc.Root.Element("packageSources").Elements("add").Attributes("value")) + // { + // if (!Path.IsPathRooted(v.Value)) + // { + // string fullPath = Path.GetFullPath(Path.Combine(f.Directory.FullName, v.Value)); + // if (!IsAncestor(new FileInfo(fullPath), Root)) + // { + // v.Value = fullPath; + // } + // } - //throw new Exception($"\nvalue = {v.Value}\n" + - // $"f.dir = {f.Directory.FullName}\n" + - // $"fullPath = {fullPath}"); + // //throw new Exception($"\nvalue = {v.Value}\n" + + // // $"f.dir = {f.Directory.FullName}\n" + + // // $"fullPath = {fullPath}"); - } + // } - using (var file = new FileStream(destinationPath, FileMode.CreateNew, FileAccess.ReadWrite)) - { - doc.Save(file, SaveOptions.None); - } - } - else - { - f.CopyTo(destinationPath); - } - } - } + // using (var file = new FileStream(destinationPath, FileMode.CreateNew, FileAccess.ReadWrite)) + // { + // doc.Save(file, SaveOptions.None); + // } + // } + // else + // { + // f.CopyTo(destinationPath); + // } + // } + //} - private void DoRestore() - { - //throw new Exception("foooooo"); - try - { - Console.WriteLine($"TestAsset Restore '{_assetName}'"); - - _operationDirectory.Refresh(); - var projFiles = _operationDirectory.GetFiles(_projectFilePattern, SearchOption.AllDirectories); - - foreach (var projFile in projFiles) - { - var restoreArgs = new string[] { "restore", projFile.FullName }; - - var commandResult = Command.Create(_dotnetExeFile.FullName, restoreArgs) - .CaptureStdOut() - .CaptureStdErr() - .Execute(); - - int exitCode = commandResult.ExitCode; - - if (exitCode != 0) - { - Console.WriteLine(commandResult.StdOut); - - Console.WriteLine(commandResult.StdErr); - - string message = string.Format($"TestAsset Restore '{_assetName}'@'{projFile.FullName}' Failed with {exitCode}"); - - throw new Exception($"TestAsset {_dotnetExeFile.FullName} {string.Join(" ", restoreArgs)}"); - } - } - } - catch (Exception e) - { - throw new Exception($"NOOOOOOOOOOOOOOOOOOOOOOOOOOOOO:\n{e.Message}"); - } - } - - private void DoBuild() - { - string[] args = new string[] { "build" }; - - Console.WriteLine($"TestAsset Build '{_assetName}'"); - - var commandResult = Command.Create(_dotnetExeFile.FullName, args) - .WorkingDirectory(_operationDirectory.FullName) - .CaptureStdOut() - .CaptureStdErr() - .Execute(); - - int exitCode = commandResult.ExitCode; - - if (exitCode != 0) - { - Console.WriteLine(commandResult.StdOut); - - Console.WriteLine(commandResult.StdErr); - - string message = string.Format($"TestAsset Build '{_assetName}' Failed with {exitCode}"); - - throw new Exception(message); - } - } - - private bool HaveSourcesChanged(ExclusiveFolderAccess folder) - { - var originalFiles = GetOriginalFileList(); - var originalFilesRebased = originalFiles.Select(f => RebasePath(f.FullName, _root.FullName, _operationDirectory.FullName)); - var trackedOriginalFiles = folder.LoadInventory(_inventoryFiles.Source); - - bool hasUntrackedFiles = originalFilesRebased.Any(a => !trackedOriginalFiles.Any(t => t.FullName.Equals(a))); - if (hasUntrackedFiles) - { - return true; - } - - bool hasMissingFiles = trackedOriginalFiles.Any(t => !File.Exists(RebasePath(t.FullName, _operationDirectory.FullName, _root.FullName))); - if (hasMissingFiles) - { - return true; - } - - foreach (var origFile in originalFiles) - { - var copiedFile = new FileInfo(RebasePath(origFile.FullName, _root.FullName, _operationDirectory.FullName)); - if (origFile.LastWriteTimeUtc != copiedFile.LastWriteTimeUtc) - { - return true; - } - } - - return false; - } - - private void RemoveCacheIfSourcesHaveChanged() - { - ExclusiveFolderAccess.Do(_dataDirectory, (folder) => { - _operationDirectory.Refresh(); - if (!_operationDirectory.Exists) - { - return; - } - - if (HaveSourcesChanged(folder)) - { - Console.WriteLine("Sources have changed................................"); - RemoveOperationFiles(); - } - }); - } private void ThrowIfTestAssetDoesNotExist() { - if (!_root.Exists) + if (!Root.Exists) { - throw new DirectoryNotFoundException($"Directory not found at '{_root.FullName}'"); + throw new DirectoryNotFoundException($"Directory not found at '{Root.FullName}'"); } } - - private class ExclusiveFolderAccess - { - private DirectoryInfo _directory; - - private ExclusiveFolderAccess(DirectoryInfo directory) - { - _directory = directory; - } - - public static void Do(DirectoryInfo directory, Action action) - { - Task.Run(async () => await ConcurrencyUtilities.ExecuteWithFileLockedAsync( - directory.FullName, - lockedToken => - { - action(new ExclusiveFolderAccess(directory)); - return Task.FromResult(new Object()); - }, - CancellationToken.None)).Wait(); - } - - public static IEnumerable Read(FileInfo file) - { - IEnumerable ret = null; - Do(file.Directory, (folder) => { - ret = folder.LoadInventory(file); - }); - - return ret; - } - - public IEnumerable LoadInventory(FileInfo file) - { - file.Refresh(); - if (!file.Exists) - { - return Enumerable.Empty(); - } - - var inventory = new List(); - foreach (var p in File.ReadAllLines(file.FullName)) - { - inventory.Add(new FileInfo(p)); - } - - return inventory; - } - - public void SaveInventory(FileInfo file, IEnumerable inventory) - { - _directory.Refresh(); - if (!_directory.Exists) - { - _directory.Create(); - } - - File.WriteAllLines(file.FullName, inventory.Select((fi) => fi.FullName).ToList()); - } - } } } diff --git a/src/Microsoft.DotNet.TestFramework/TestAssetInstance.cs b/src/Microsoft.DotNet.TestFramework/TestAssetInstance.cs index 0f7101b94..f86b66451 100644 --- a/src/Microsoft.DotNet.TestFramework/TestAssetInstance.cs +++ b/src/Microsoft.DotNet.TestFramework/TestAssetInstance.cs @@ -17,6 +17,18 @@ namespace Microsoft.DotNet.TestFramework { public class TestAssetInstance { + public DirectoryInfo MigrationBackupRoot { get; } + + public DirectoryInfo Root { get; } + + public TestAssetInfo TestAssetInfo { get; } + + private bool _filesCopied = false; + + private bool _restored = false; + + private bool _built = false; + public TestAssetInstance(TestAssetInfo testAssetInfo, DirectoryInfo root) { if (testAssetInfo == null) @@ -48,36 +60,44 @@ namespace Microsoft.DotNet.TestFramework } } - public DirectoryInfo MigrationBackupRoot { get; } - - public DirectoryInfo Root { get; } - - public TestAssetInfo TestAssetInfo { get; } - - public TestAssetInstance WithSourceFiles() { - var filesToCopy = TestAssetInfo.GetSourceFiles(); + if (!_filesCopied) + { + var filesToCopy = TestAssetInfo.GetSourceFiles(); - CopyFiles(filesToCopy); + CopyFiles(filesToCopy); + + _filesCopied = true; + } return this; } public TestAssetInstance WithRestoreFiles() { - var filesToCopy = TestAssetInfo.GetRestoreFiles(); + if (!_restored) + { + WithSourceFiles(); - CopyFiles(filesToCopy); + RestoreAllProjects(); + + _restored = true; + } return this; } public TestAssetInstance WithBuildFiles() { - var filesToCopy = TestAssetInfo.GetBuildFiles(); + if (!_built) + { + WithRestoreFiles(); - CopyFiles(filesToCopy); + BuildRootProjectOrSolution(); + + _built = true; + } return this; } @@ -171,5 +191,69 @@ namespace Microsoft.DotNet.TestFramework file.CopyTo(newPath); } } + + private void BuildRootProjectOrSolution() + { + string[] args = new string[] { "build" }; + + Console.WriteLine($"TestAsset Build '{TestAssetInfo.AssetName}'"); + + var commandResult = Command.Create(TestAssetInfo.DotnetExeFile.FullName, args) + .WorkingDirectory(Root.FullName) + .CaptureStdOut() + .CaptureStdErr() + .Execute(); + + int exitCode = commandResult.ExitCode; + + if (exitCode != 0) + { + Console.WriteLine(commandResult.StdOut); + + Console.WriteLine(commandResult.StdErr); + + string message = string.Format($"TestAsset Build '{TestAssetInfo.AssetName}' Failed with {exitCode}"); + + throw new Exception(message); + } + } + + private IEnumerable GetProjectFiles() + { + return Root.GetFiles(TestAssetInfo.ProjectFilePattern, SearchOption.AllDirectories); + } + + private void Restore(FileInfo projectFile) + { + var restoreArgs = new string[] { "restore", projectFile.FullName }; + + var commandResult = Command.Create(TestAssetInfo.DotnetExeFile.FullName, restoreArgs) + .CaptureStdOut() + .CaptureStdErr() + .Execute(); + + int exitCode = commandResult.ExitCode; + + if (exitCode != 0) + { + Console.WriteLine(commandResult.StdOut); + + Console.WriteLine(commandResult.StdErr); + + string message = string.Format($"TestAsset Restore '{TestAssetInfo.AssetName}'@'{projectFile.FullName}' Failed with {exitCode}"); + + throw new Exception($"TestAsset {TestAssetInfo.DotnetExeFile.FullName} {string.Join(" ", restoreArgs)}"); + } + } + + private void RestoreAllProjects() + { + Console.WriteLine($"TestAsset Restore '{TestAssetInfo.AssetName}'"); + + foreach (var projFile in GetProjectFiles()) + { + Restore(projFile); + } + } } } From dbd278e65e6d993c3e14b7796e4acf6723cdad03 Mon Sep 17 00:00:00 2001 From: Krzysztof Wicher Date: Fri, 10 Feb 2017 10:57:36 -0800 Subject: [PATCH 3/5] adjust nuget.config paths --- .../TestAssetInfo.cs | 90 ------------------- .../TestAssetInstance.cs | 74 +++++++++++++-- 2 files changed, 65 insertions(+), 99 deletions(-) diff --git a/src/Microsoft.DotNet.TestFramework/TestAssetInfo.cs b/src/Microsoft.DotNet.TestFramework/TestAssetInfo.cs index c8502ec63..f5ca0aebe 100644 --- a/src/Microsoft.DotNet.TestFramework/TestAssetInfo.cs +++ b/src/Microsoft.DotNet.TestFramework/TestAssetInfo.cs @@ -6,13 +6,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.CompilerServices; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.DotNet.Cli.Utils; -using Microsoft.DotNet.PlatformAbstractions; -using NuGet.Common; -using PathUtility = Microsoft.DotNet.Tools.Common.PathUtility; -using System.Xml.Linq; namespace Microsoft.DotNet.TestFramework { @@ -57,8 +50,6 @@ namespace Microsoft.DotNet.TestFramework DotnetExeFile = dotnetExeFile; ProjectFilePattern = projectFilePattern; - - //throw new Exception($"root = {_root}\nassetName = {_assetName}\ndotnetExeFile = {_dotnetExeFile}\nprojectFilePattern = {_projectFilePattern}\ndataDir = {_dataDirectory}\ndirectoriesToExclude = {string.Join(";",_directoriesToExclude)}"); } public TestAssetInstance CreateInstance([CallerMemberName] string callingMethod = "", string identifier = "") @@ -88,87 +79,6 @@ namespace Microsoft.DotNet.TestFramework return new DirectoryInfo(Path.Combine(baseDirectory, callingMethod + identifier, AssetName)); } - private static string RebasePath(string path, string oldBaseDirectory, string newBaseDirectory) - { - path = Path.IsPathRooted(path) ? PathUtility.GetRelativePath(PathUtility.EnsureTrailingSlash(oldBaseDirectory), path) : path; - return Path.Combine(newBaseDirectory, path); - } - - private bool IsAncestor(FileInfo file, DirectoryInfo maybeAncestor) - { - var dir = file.Directory; - do - { - if (string.Equals(maybeAncestor.FullName, dir.FullName, StringComparison.OrdinalIgnoreCase)) - { - return true; - } - - dir = dir.Parent; - } - while (dir != null); - - return false; - } - - //private void DoCopyFiles() - //{ - // Console.WriteLine($"TestAsset CopyFiles '{AssetName}'"); - - // _operationDirectory.Refresh(); - // if (!_operationDirectory.Exists) - // { - // _operationDirectory.Create(); - // } - // else - // { - // if (_operationDirectory.GetFiles().Any()) - // { - // throw new Exception("operation files folder not empty"); - // } - // } - - // foreach (var f in GetOriginalFileList()) - // { - // string destinationPath = RebasePath(f.FullName, Root.FullName, _operationDirectory.FullName); - // var destinationDir = new FileInfo(destinationPath).Directory; - // if (!destinationDir.Exists) - // { - // destinationDir.Create(); - // } - // if (string.Equals(f.Name, "nuget.config", StringComparison.OrdinalIgnoreCase)) - // { - // var doc = XDocument.Load(f.FullName, LoadOptions.PreserveWhitespace); - // foreach (var v in doc.Root.Element("packageSources").Elements("add").Attributes("value")) - // { - // if (!Path.IsPathRooted(v.Value)) - // { - // string fullPath = Path.GetFullPath(Path.Combine(f.Directory.FullName, v.Value)); - // if (!IsAncestor(new FileInfo(fullPath), Root)) - // { - // v.Value = fullPath; - // } - // } - - // //throw new Exception($"\nvalue = {v.Value}\n" + - // // $"f.dir = {f.Directory.FullName}\n" + - // // $"fullPath = {fullPath}"); - - // } - - // using (var file = new FileStream(destinationPath, FileMode.CreateNew, FileAccess.ReadWrite)) - // { - // doc.Save(file, SaveOptions.None); - // } - // } - // else - // { - // f.CopyTo(destinationPath); - // } - // } - //} - - private void ThrowIfTestAssetDoesNotExist() { if (!Root.Exists) diff --git a/src/Microsoft.DotNet.TestFramework/TestAssetInstance.cs b/src/Microsoft.DotNet.TestFramework/TestAssetInstance.cs index f86b66451..94a13bb1a 100644 --- a/src/Microsoft.DotNet.TestFramework/TestAssetInstance.cs +++ b/src/Microsoft.DotNet.TestFramework/TestAssetInstance.cs @@ -35,7 +35,7 @@ namespace Microsoft.DotNet.TestFramework { throw new ArgumentException(nameof(testAssetInfo)); } - + if (root == null) { throw new ArgumentException(nameof(root)); @@ -64,9 +64,7 @@ namespace Microsoft.DotNet.TestFramework { if (!_filesCopied) { - var filesToCopy = TestAssetInfo.GetSourceFiles(); - - CopyFiles(filesToCopy); + CopySourceFiles(); _filesCopied = true; } @@ -176,19 +174,77 @@ namespace Microsoft.DotNet.TestFramework }); } - private void CopyFiles(IEnumerable filesToCopy) + private static string RebasePath(string path, string oldBaseDirectory, string newBaseDirectory) { + path = Path.IsPathRooted(path) ? PathUtility.GetRelativePath(PathUtility.EnsureTrailingSlash(oldBaseDirectory), path) : path; + return Path.Combine(newBaseDirectory, path); + } + + private void CopySourceFiles() + { + var filesToCopy = TestAssetInfo.GetSourceFiles(); foreach (var file in filesToCopy) { - var relativePath = file.FullName.Substring(TestAssetInfo.Root.FullName.Length + 1); - - var newPath = Path.Combine(Root.FullName, relativePath); + var newPath = RebasePath(file.FullName, TestAssetInfo.Root.FullName, Root.FullName); var newFile = new FileInfo(newPath); PathUtility.EnsureDirectoryExists(newFile.Directory.FullName); - file.CopyTo(newPath); + CopyFileAdjustingPaths(file, newFile); + } + } + + private bool IsAncestor(FileInfo file, DirectoryInfo maybeAncestor) + { + var dir = file.Directory; + do + { + if (string.Equals(maybeAncestor.FullName, dir.FullName, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + + dir = dir.Parent; + } + while (dir != null); + + return false; + } + + private void CopyFileAdjustingPaths(FileInfo source, FileInfo destination) + { + if (string.Equals(source.Name, "nuget.config", StringComparison.OrdinalIgnoreCase)) + { + CopyNugetConfigAdjustingPath(source, destination); + } + else + { + source.CopyTo(destination.FullName); + } + } + + private void CopyNugetConfigAdjustingPath(FileInfo source, FileInfo destination) + { + var doc = XDocument.Load(source.FullName, LoadOptions.PreserveWhitespace); + foreach (var packageSource in doc.Root.Element("packageSources").Elements("add").Attributes("value")) + { + if (!Path.IsPathRooted(packageSource.Value)) + { + string fullPathAtSource = Path.GetFullPath(Path.Combine(source.Directory.FullName, packageSource.Value)); + if (!IsAncestor(new FileInfo(fullPathAtSource), TestAssetInfo.Root)) + { + packageSource.Value = fullPathAtSource; + } + } + + using (var file = new FileStream( + destination.FullName, + FileMode.CreateNew, + FileAccess.ReadWrite)) + { + doc.Save(file, SaveOptions.None); + } } } From e3b36b2b654c71dac26ebe4ebf2ea96b0178415f Mon Sep 17 00:00:00 2001 From: Krzysztof Wicher Date: Fri, 10 Feb 2017 14:27:41 -0800 Subject: [PATCH 4/5] remove leftover from debugging --- src/Microsoft.DotNet.TestFramework/TestAssetInstance.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.DotNet.TestFramework/TestAssetInstance.cs b/src/Microsoft.DotNet.TestFramework/TestAssetInstance.cs index 94a13bb1a..0e4d5bbe4 100644 --- a/src/Microsoft.DotNet.TestFramework/TestAssetInstance.cs +++ b/src/Microsoft.DotNet.TestFramework/TestAssetInstance.cs @@ -298,7 +298,7 @@ namespace Microsoft.DotNet.TestFramework string message = string.Format($"TestAsset Restore '{TestAssetInfo.AssetName}'@'{projectFile.FullName}' Failed with {exitCode}"); - throw new Exception($"TestAsset {TestAssetInfo.DotnetExeFile.FullName} {string.Join(" ", restoreArgs)}"); + throw new Exception(message); } } From 29175985447c807cbac9bd48125646870d7fe0a8 Mon Sep 17 00:00:00 2001 From: Krzysztof Wicher Date: Fri, 10 Feb 2017 15:50:48 -0800 Subject: [PATCH 5/5] Remove IsAncestor and use PathUtility.IsChildOfDirectory instead --- .../TestAssetInstance.cs | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/src/Microsoft.DotNet.TestFramework/TestAssetInstance.cs b/src/Microsoft.DotNet.TestFramework/TestAssetInstance.cs index 0e4d5bbe4..1c3385297 100644 --- a/src/Microsoft.DotNet.TestFramework/TestAssetInstance.cs +++ b/src/Microsoft.DotNet.TestFramework/TestAssetInstance.cs @@ -195,23 +195,6 @@ namespace Microsoft.DotNet.TestFramework } } - private bool IsAncestor(FileInfo file, DirectoryInfo maybeAncestor) - { - var dir = file.Directory; - do - { - if (string.Equals(maybeAncestor.FullName, dir.FullName, StringComparison.OrdinalIgnoreCase)) - { - return true; - } - - dir = dir.Parent; - } - while (dir != null); - - return false; - } - private void CopyFileAdjustingPaths(FileInfo source, FileInfo destination) { if (string.Equals(source.Name, "nuget.config", StringComparison.OrdinalIgnoreCase)) @@ -232,7 +215,7 @@ namespace Microsoft.DotNet.TestFramework if (!Path.IsPathRooted(packageSource.Value)) { string fullPathAtSource = Path.GetFullPath(Path.Combine(source.Directory.FullName, packageSource.Value)); - if (!IsAncestor(new FileInfo(fullPathAtSource), TestAssetInfo.Root)) + if (!PathUtility.IsChildOfDirectory(TestAssetInfo.Root.FullName, fullPathAtSource)) { packageSource.Value = fullPathAtSource; }