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); + } + } } }