diff --git a/MLS.Agent.Tests/ApiViaHttpTests.cs b/MLS.Agent.Tests/ApiViaHttpTests.cs index dafdca455..562071470 100644 --- a/MLS.Agent.Tests/ApiViaHttpTests.cs +++ b/MLS.Agent.Tests/ApiViaHttpTests.cs @@ -30,6 +30,7 @@ using WorkspaceServer.Tests.TestUtility; using CodeManipulation = WorkspaceServer.Tests.CodeManipulation; using SourceFile = Microsoft.DotNet.Try.Protocol.ClientApi.SourceFile; +using WorkspaceServer; namespace MLS.Agent.Tests { @@ -995,7 +996,7 @@ public async Task Scaffolding_HTML_trydotnet_js_autoEnable_useWasmRunner_is_true var (name, addSource) = await Create.NupkgWithBlazorEnabled("packageName"); var startupOptions = new StartupOptions( - dir: TestAssets.SampleConsole, + rootDirectory: new FileSystemDirectoryAccessor(TestAssets.SampleConsole), addPackageSource: new WorkspaceServer.PackageSource(addSource.FullName), package: name); @@ -1027,7 +1028,7 @@ public async Task Is_able_to_serve_static_files() using (var disposableDirectory = DisposableDirectory.Create()) { System.IO.File.WriteAllText(Path.Combine(disposableDirectory.Directory.FullName, "a.js"), "alert('This is an alert from javascript');"); - var options = new StartupOptions(dir: disposableDirectory.Directory); + var options = new StartupOptions(rootDirectory: new FileSystemDirectoryAccessor(disposableDirectory.Directory)); using (var agent = new AgentService(options: options)) { diff --git a/MLS.Agent.Tests/CommandLine/CommandLineParserTests.cs b/MLS.Agent.Tests/CommandLine/CommandLineParserTests.cs index 5fe337bbc..2c04c0eb4 100644 --- a/MLS.Agent.Tests/CommandLine/CommandLineParserTests.cs +++ b/MLS.Agent.Tests/CommandLine/CommandLineParserTests.cs @@ -8,12 +8,14 @@ using System.IO; using System.Threading.Tasks; using FluentAssertions; +using Microsoft.DotNet.Try.Markdown; using Microsoft.Extensions.DependencyInjection; using MLS.Agent.CommandLine; using WorkspaceServer; using WorkspaceServer.Tests.TestUtility; using Xunit; using Xunit.Abstractions; +using WorkspaceServer.Tests; namespace MLS.Agent.Tests.CommandLine { @@ -96,7 +98,7 @@ public async Task Parse_root_directory_with_a_valid_path_succeeds() { var path = TestAssets.SampleConsole.FullName; await _parser.InvokeAsync(new[] { path }, _console); - _startOptions.Dir.FullName.Should().Be(path); + _startOptions.RootDirectory.GetFullyQualifiedRoot().FullName.Should().Be(path + Path.DirectorySeparatorChar); } [Fact] @@ -150,7 +152,7 @@ public async Task It_parses_the_package_version_option() public async Task Parse_empty_command_line_has_current_directory_as_root_directory() { await _parser.InvokeAsync("", _console); - _startOptions.Dir.FullName.Should().Be(Directory.GetCurrentDirectory()); + _startOptions.RootDirectory.GetFullyQualifiedRoot().FullName.Should().Be(Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar); } [Fact] @@ -340,7 +342,14 @@ public async Task Verify_argument_specifies_root_directory() { var directory = Path.GetDirectoryName(typeof(VerifyCommand).Assembly.Location); await _parser.InvokeAsync($"verify {directory}", _console); - _verifyOptions.Dir.FullName.Should().Be(directory); + _verifyOptions.RootDirectory.GetFullyQualifiedRoot().FullName.Should().Be(directory + Path.DirectorySeparatorChar); + } + + [Fact] + public async Task Verify_takes_current_directory_as_default_if_none_is_specified() + { + await _parser.InvokeAsync($"verify", _console); + _verifyOptions.RootDirectory.GetFullyQualifiedRoot().FullName.Should().Be(Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar); } [Fact] @@ -366,7 +375,7 @@ public async Task jupyter_parses_connection_file_path() var binder = new ModelBinder(); - var options = (JupyterOptions) binder.CreateInstance(new BindingContext(result)); + var options = (JupyterOptions)binder.CreateInstance(new BindingContext(result)); options .ConnectionFile @@ -386,7 +395,7 @@ public async Task jupyter_returns_error_if_connection_file_path_does_not_exits() testConsole.Error.ToString().Should().Contain("File does not exist: not_exist.json"); } - [Fact(Skip ="Skipped until System.CommandLine allows subcommands to skip the arguments from the main command")] + [Fact(Skip = "Skipped until System.CommandLine allows subcommands to skip the arguments from the main command")] public async Task jupyter_returns_error_if_connection_file_path_is_not_passed() { var testConsole = new TestConsole(); diff --git a/MLS.Agent.Tests/CommandLine/DemoCommandTests.cs b/MLS.Agent.Tests/CommandLine/DemoCommandTests.cs index 4428dbf2a..39008c489 100644 --- a/MLS.Agent.Tests/CommandLine/DemoCommandTests.cs +++ b/MLS.Agent.Tests/CommandLine/DemoCommandTests.cs @@ -36,10 +36,8 @@ public async Task Demo_project_passes_verification() await DemoCommand.Do(new DemoOptions(output: outputDirectory), console); var resultCode = await VerifyCommand.Do( - new VerifyOptions(dir: outputDirectory), + new VerifyOptions(new FileSystemDirectoryAccessor(outputDirectory)), console, - () => new FileSystemDirectoryAccessor(outputDirectory), - new PackageRegistry(), startupOptions: new StartupOptions(package: packageFile.FullName)); _output.WriteLine(console.Out.ToString()); @@ -63,10 +61,8 @@ public async Task Demo_sources_pass_verification() await DemoCommand.Do(new DemoOptions(output: demoSourcesDir), console); var resultCode = await VerifyCommand.Do( - new VerifyOptions(dir: demoSourcesDir), + new VerifyOptions(new FileSystemDirectoryAccessor(demoSourcesDir)), console, - () => new FileSystemDirectoryAccessor(demoSourcesDir), - new PackageRegistry(), new StartupOptions(package: packageFile.FullName)); _output.WriteLine(console.Out.ToString()); @@ -110,10 +106,8 @@ await DemoCommand.Do( startServer: (options, context) => { }); var resultCode = await VerifyCommand.Do( - new VerifyOptions(dir: outputDirectory), - console, - () => new FileSystemDirectoryAccessor(outputDirectory), - new PackageRegistry()); + new VerifyOptions(new FileSystemDirectoryAccessor(outputDirectory)), + console); resultCode.Should().NotBe(0); } @@ -132,10 +126,8 @@ await DemoCommand.Do( (options, context) => startupOptions = options); await VerifyCommand.Do( - new VerifyOptions(dir: outputDirectory), - console, - () => new FileSystemDirectoryAccessor(outputDirectory), - new PackageRegistry()); + new VerifyOptions(new FileSystemDirectoryAccessor(outputDirectory)), + console); _output.WriteLine(console.Out.ToString()); _output.WriteLine(console.Error.ToString()); diff --git a/MLS.Agent.Tests/CommandLine/StartupOptionsTests.cs b/MLS.Agent.Tests/CommandLine/StartupOptionsTests.cs index 6f24044c6..03dae06fb 100644 --- a/MLS.Agent.Tests/CommandLine/StartupOptionsTests.cs +++ b/MLS.Agent.Tests/CommandLine/StartupOptionsTests.cs @@ -7,6 +7,7 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Hosting; using MLS.Agent.CommandLine; +using WorkspaceServer; using Xunit; namespace MLS.Agent.Tests.CommandLine @@ -16,7 +17,7 @@ public class StartupOptionsTests [Fact] public void When_Production_is_true_and_in_hosted_mode_then_EnvironmentName_is_production() { - var options = new StartupOptions(production: true, dir: null); + var options = new StartupOptions(production: true, rootDirectory: null); options.EnvironmentName.Should().Be(Environments.Production); } @@ -24,7 +25,7 @@ public void When_Production_is_true_and_in_hosted_mode_then_EnvironmentName_is_p [Fact] public void When_Production_is_true_and_not_in_hosted_mode_then_EnvironmentName_is_production() { - var options = new StartupOptions(production: true, dir: new DirectoryInfo(Directory.GetCurrentDirectory())); + var options = new StartupOptions(production: true, rootDirectory: new FileSystemDirectoryAccessor(Directory.GetCurrentDirectory())); options.EnvironmentName.Should().Be(Environments.Production); } @@ -32,7 +33,7 @@ public void When_Production_is_true_and_not_in_hosted_mode_then_EnvironmentName_ [Fact] public void When_not_in_hosted_mode_then_EnvironmentName_is_production() { - var options = new StartupOptions(dir: new DirectoryInfo(Directory.GetCurrentDirectory())); + var options = new StartupOptions(rootDirectory: new FileSystemDirectoryAccessor(Directory.GetCurrentDirectory())); options.EnvironmentName.Should().Be(Environments.Production); } diff --git a/MLS.Agent.Tests/CommandLine/VerifyCommandTests.cs b/MLS.Agent.Tests/CommandLine/VerifyCommandTests.cs index 384f7d966..89cb5279f 100644 --- a/MLS.Agent.Tests/CommandLine/VerifyCommandTests.cs +++ b/MLS.Agent.Tests/CommandLine/VerifyCommandTests.cs @@ -89,11 +89,7 @@ public async Task Errors_are_written_to_std_out() var console = new TestConsole(); - await VerifyCommand.Do( - new VerifyOptions(root), - console, - () => directoryAccessor, - PackageRegistry.CreateForTryMode(root)); + await VerifyCommand.Do(new VerifyOptions(directoryAccessor), console); console.Out .ToString() @@ -118,11 +114,7 @@ public async Task Files_are_listed() var console = new TestConsole(); - await VerifyCommand.Do( - new VerifyOptions(root), - console, - () => directoryAccessor, - PackageRegistry.CreateForTryMode(root)); + await VerifyCommand.Do(new VerifyOptions(directoryAccessor), console); _output.WriteLine(console.Out.ToString()); @@ -153,11 +145,7 @@ public async Task Fails_if_language_is_not_compatible_with_backing_project() var console = new TestConsole(); - await VerifyCommand.Do( - new VerifyOptions(root), - console, - () => directoryAccessor, - PackageRegistry.CreateForTryMode(root)); + await VerifyCommand.Do(new VerifyOptions(directoryAccessor), console); _output.WriteLine(console.Out.ToString()); @@ -195,11 +183,7 @@ public class EmptyClassTwo {} var console = new TestConsole(); - var resultCode = await VerifyCommand.Do( - new VerifyOptions(root), - console, - () => directoryAccessor, - PackageRegistry.CreateForTryMode(root)); + var resultCode = await VerifyCommand.Do(new VerifyOptions(directoryAccessor), console); _output.WriteLine(console.Out.ToString()); @@ -227,11 +211,7 @@ public async Task When_projects_are_deeper_than_root_it_succeeds() var console = new TestConsole(); - var resultCode = await VerifyCommand.Do( - new VerifyOptions(root), - console, - () => directoryAccessor, - PackageRegistry.CreateForTryMode(root)); + var resultCode = await VerifyCommand.Do(new VerifyOptions(directoryAccessor), console); _output.WriteLine(console.Out.ToString()); @@ -255,17 +235,13 @@ public async Task With_non_editable_code_block_targeting_regions_with_non_compil var console = new TestConsole(); - var resultCode = await VerifyCommand.Do( - new VerifyOptions(root), - console, - () => directoryAccessor, - PackageRegistry.CreateForTryMode(root)); + var resultCode = await VerifyCommand.Do(new VerifyOptions(directoryAccessor), console); _output.WriteLine(console.Out.ToString()); resultCode.Should().NotBe(0); } - + [Fact] public async Task When_there_are_no_markdown_errors_then_return_code_is_0() { @@ -283,11 +259,7 @@ public async Task When_there_are_no_markdown_errors_then_return_code_is_0() var console = new TestConsole(); - var resultCode = await VerifyCommand.Do( - new VerifyOptions(rootDirectory), - console, - () => directoryAccessor, - PackageRegistry.CreateForTryMode(rootDirectory)); + var resultCode = await VerifyCommand.Do(new VerifyOptions(directoryAccessor), console); _output.WriteLine(console.Out.ToString()); @@ -325,11 +297,7 @@ public static void Main(string[] args) var console = new TestConsole(); - var resultCode = await VerifyCommand.Do( - new VerifyOptions(rootDirectory), - console, - () => directoryAccessor, - PackageRegistry.CreateForTryMode(rootDirectory)); + var resultCode = await VerifyCommand.Do(new VerifyOptions(directoryAccessor), console); _output.WriteLine(console.Out.ToString()); @@ -346,11 +314,7 @@ public async Task When_there_are_no_files_found_then_return_code_is_nonzero() var console = new TestConsole(); - var resultCode = await VerifyCommand.Do( - new VerifyOptions(rootDirectory), - console, - () => directoryAccessor, - PackageRegistry.CreateForTryMode(rootDirectory)); + var resultCode = await VerifyCommand.Do(new VerifyOptions(directoryAccessor), console); console.Error.ToString().Should().Contain("No markdown files found"); resultCode.Should().NotBe(0); @@ -380,11 +344,7 @@ public async Task Returns_an_error_when_a_session_has_more_than_one_package_or_p var console = new TestConsole(); - var resultCode = await VerifyCommand.Do( - new VerifyOptions(rootDirectory), - console, - () => directoryAccessor, - PackageRegistry.CreateForTryMode(rootDirectory)); + var resultCode = await VerifyCommand.Do(new VerifyOptions(directoryAccessor), console); console.Out.ToString().Should().Contain("Session cannot span projects or packages: --session one"); @@ -426,11 +386,7 @@ public static void Main(string[] args) var console = new TestConsole(); - var resultCode = await VerifyCommand.Do( - new VerifyOptions(directory), - console, - () => directoryAccessor, - PackageRegistry.CreateForTryMode(directory)); + var resultCode = await VerifyCommand.Do(new VerifyOptions(directoryAccessor), console); _output.WriteLine(console.Out.ToString()); @@ -467,11 +423,7 @@ public static void Main(string[] args) DOES NOT COMPILE var console = new TestConsole(); - var resultCode = await VerifyCommand.Do( - new VerifyOptions(rootDirectory), - console, - () => directoryAccessor, - PackageRegistry.CreateForTryMode(rootDirectory)); + var resultCode = await VerifyCommand.Do(new VerifyOptions(directoryAccessor), console); _output.WriteLine(console.Out.ToString()); @@ -516,11 +468,7 @@ DOES NOT COMPILE var console = new TestConsole(); - var resultCode = await VerifyCommand.Do( - new VerifyOptions(rootDirectory), - console, - () => directoryAccessor, - PackageRegistry.CreateForTryMode(rootDirectory)); + var resultCode = await VerifyCommand.Do(new VerifyOptions(directoryAccessor), console); _output.WriteLine(console.Out.ToString()); @@ -547,11 +495,7 @@ public async Task When_there_are_code_fence_options_errors_then_compilation_is_n var console = new TestConsole(); - await VerifyCommand.Do( - new VerifyOptions(root), - console, - () => directoryAccessor, - PackageRegistry.CreateForTryMode(root)); + await VerifyCommand.Do(new VerifyOptions(directoryAccessor), console); _output.WriteLine(console.Out.ToString()); @@ -589,23 +533,14 @@ public static void Main(string[] args) var console = new TestConsole(); - var packageRegistry = PackageRegistry.CreateForTryMode(rootDirectory); - var resultCode = await VerifyCommand.Do( - new VerifyOptions(rootDirectory), - console, - () => directoryAccessor, - packageRegistry); + var resultCode = await VerifyCommand.Do(new VerifyOptions(directoryAccessor), console); _output.WriteLine(console.Out.ToString()); resultCode.Should().Be(0); File.WriteAllText(directoryAccessor.GetFullyQualifiedPath(new RelativeFilePath("Sample.cs")).FullName, "DOES NOT COMPILE"); - resultCode = await VerifyCommand.Do( - new VerifyOptions(rootDirectory), - console, - () => directoryAccessor, - packageRegistry); + resultCode = await VerifyCommand.Do(new VerifyOptions(directoryAccessor), console); _output.WriteLine(console.Out.ToString()); @@ -659,22 +594,14 @@ public static void Main(string[] args) DOES NOT COMPILE var console = new TestConsole(); - var packageRegistry = PackageRegistry.CreateForTryMode(rootDirectory); - var resultCode = await VerifyCommand.Do( - new VerifyOptions(rootDirectory), - console, - () => directoryAccessor, - packageRegistry); + + var resultCode = await VerifyCommand.Do(new VerifyOptions(directoryAccessor), console); resultCode.Should().Be(0); File.WriteAllText(directoryAccessor.GetFullyQualifiedPath(new RelativeFilePath("Program.cs")).FullName, invalidCode); - resultCode = await VerifyCommand.Do( - new VerifyOptions(rootDirectory), - console, - () => directoryAccessor, - packageRegistry); + resultCode = await VerifyCommand.Do(new VerifyOptions(directoryAccessor), console); _output.WriteLine(console.Out.ToString()); @@ -715,11 +642,7 @@ public async Task When_standalone_markdown_with_non_editable_code_block_targetin var console = new TestConsole(); var project = directoryAccessor.GetFullyQualifiedPath(new RelativeFilePath("./subFolder/some.csproj")); - var resultCode = await VerifyCommand.Do( - new VerifyOptions(root), - console, - () => directoryAccessor, - PackageRegistry.CreateForTryMode(root), + var resultCode = await VerifyCommand.Do(new VerifyOptions(directoryAccessor), console, new StartupOptions(package: project.FullName)); _output.WriteLine(console.Out.ToString()); @@ -753,11 +676,7 @@ public class EmptyClassTwo {{}} var console = new TestConsole(); var project = directoryAccessor.GetFullyQualifiedPath(new RelativeFilePath("./subFolder/some.csproj")); - var resultCode = await VerifyCommand.Do( - new VerifyOptions(root), - console, - () => directoryAccessor, - PackageRegistry.CreateForTryMode(root), + var resultCode = await VerifyCommand.Do(new VerifyOptions(directoryAccessor), console, new StartupOptions(package: project.FullName) ); @@ -791,11 +710,7 @@ DOES NOT COMPILE var console = new TestConsole(); var project = directoryAccessor.GetFullyQualifiedPath(new RelativeFilePath("./subFolder/some.csproj")); - var resultCode = await VerifyCommand.Do( - new VerifyOptions(root), - console, - () => directoryAccessor, - PackageRegistry.CreateForTryMode(root), + var resultCode = await VerifyCommand.Do(new VerifyOptions(directoryAccessor), console, new StartupOptions(package: project.FullName)); _output.WriteLine(console.Out.ToString()); @@ -824,11 +739,7 @@ public async Task When_markdown_has_Program_with_a_region_and_markdown_has_desti var console = new TestConsole(); var project = directoryAccessor.GetFullyQualifiedPath(new RelativeFilePath("./subFolder/some.csproj")); - var resultCode = await VerifyCommand.Do( - new VerifyOptions(root), - console, - () => directoryAccessor, - PackageRegistry.CreateForTryMode(root), + var resultCode = await VerifyCommand.Do(new VerifyOptions(directoryAccessor), console, new StartupOptions(package: project.FullName) ); diff --git a/MLS.Agent.Tests/DocumentationAPITests.cs b/MLS.Agent.Tests/DocumentationAPITests.cs index 3c38c7edf..773e2f369 100644 --- a/MLS.Agent.Tests/DocumentationAPITests.cs +++ b/MLS.Agent.Tests/DocumentationAPITests.cs @@ -13,6 +13,7 @@ using Microsoft.DotNet.Try.Markdown; using MLS.Agent.CommandLine; using Recipes; +using WorkspaceServer; using WorkspaceServer.Tests; using WorkspaceServer.Tests.TestUtility; using Xunit; @@ -24,7 +25,7 @@ public class DocumentationAPITests [Fact] public async Task Request_for_non_existent_markdown_file_returns_404() { - using (var agent = new AgentService(new StartupOptions(dir: TestAssets.SampleConsole))) + using (var agent = new AgentService(new StartupOptions(rootDirectory: new FileSystemDirectoryAccessor(TestAssets.SampleConsole)))) { var response = await agent.GetAsync(@"/DOESNOTEXIST"); @@ -35,7 +36,7 @@ public async Task Request_for_non_existent_markdown_file_returns_404() [Fact] public async Task Return_html_for_an_existing_markdown_file() { - using (var agent = new AgentService(new StartupOptions(dir: TestAssets.SampleConsole))) + using (var agent = new AgentService(new StartupOptions(rootDirectory: new FileSystemDirectoryAccessor(TestAssets.SampleConsole)))) { var response = await agent.GetAsync(@"Readme.md"); @@ -50,7 +51,7 @@ public async Task Return_html_for_an_existing_markdown_file() [Fact] public async Task Return_html_for_existing_markdown_files_in_a_subdirectory() { - using (var agent = new AgentService(new StartupOptions(dir: TestAssets.SampleConsole))) + using (var agent = new AgentService(new StartupOptions(rootDirectory: new FileSystemDirectoryAccessor(TestAssets.SampleConsole)))) { var response = await agent.GetAsync(@"Subdirectory/Tutorial.md"); @@ -64,7 +65,7 @@ public async Task Return_html_for_existing_markdown_files_in_a_subdirectory() [Fact] public async Task Lists_markdown_files_when_a_folder_is_requested() { - using (var agent = new AgentService(new StartupOptions(dir: TestAssets.SampleConsole))) + using (var agent = new AgentService(new StartupOptions(rootDirectory: new FileSystemDirectoryAccessor(TestAssets.SampleConsole)))) { var response = await agent.GetAsync(@"/"); @@ -88,7 +89,7 @@ public async Task Lists_markdown_files_when_a_folder_is_requested() [Fact] public async Task Scaffolding_HTML_includes_trydotnet_js_script_link() { - using (var agent = new AgentService(new StartupOptions(dir: TestAssets.SampleConsole))) + using (var agent = new AgentService(new StartupOptions(rootDirectory: new FileSystemDirectoryAccessor(TestAssets.SampleConsole)))) { var response = await agent.GetAsync(@"Subdirectory/Tutorial.md"); @@ -112,7 +113,7 @@ public async Task Scaffolding_HTML_includes_trydotnet_js_script_link() [Fact] public async Task Scaffolding_HTML_includes_trydotnet_js_autoEnable_invocation_with_useBlazor_defaulting_to_false() { - using (var agent = new AgentService(new StartupOptions(dir: TestAssets.SampleConsole))) + using (var agent = new AgentService(new StartupOptions(rootDirectory: new FileSystemDirectoryAccessor(TestAssets.SampleConsole)))) { var response = await agent.GetAsync(@"Subdirectory/Tutorial.md"); @@ -140,7 +141,7 @@ public async Task Scaffolding_HTML_trydotnet_js_autoEnable_useBlazor_is_true_whe var (name, addSource) = await Create.NupkgWithBlazorEnabled("packageName"); var startupOptions = new StartupOptions( - dir: TestAssets.SampleConsole, + rootDirectory: new FileSystemDirectoryAccessor(TestAssets.SampleConsole), addPackageSource: new WorkspaceServer.PackageSource(addSource.FullName), package: name); @@ -182,7 +183,7 @@ public async Task Scaffolding_HTML_trydotnet_js_autoEnable_useBlazor_is_true_whe File.WriteAllText(path, text); var startupOptions = new StartupOptions( - dir: dir.Directory, + rootDirectory: new FileSystemDirectoryAccessor(dir.Directory), addPackageSource: new WorkspaceServer.PackageSource(addSource.FullName)); using (var agent = new AgentService(startupOptions)) @@ -215,7 +216,7 @@ public async Task When_relative_uri_is_specified_then_it_opens_to_that_page() using (var clock = VirtualClock.Start()) using (var agent = new AgentService(new StartupOptions( - dir: TestAssets.SampleConsole, + rootDirectory: new FileSystemDirectoryAccessor(TestAssets.SampleConsole), uri: launchUri))) { await clock.Wait(5.Seconds()); @@ -241,7 +242,7 @@ public async Task When_readme_file_is_on_root_browser_opens_there() var root = directoryAccessor.GetFullyQualifiedPath(new RelativeDirectoryPath(".")) as DirectoryInfo; - var options = new StartupOptions(dir: root); + var options = new StartupOptions(rootDirectory: new FileSystemDirectoryAccessor(root)); using (var clock = VirtualClock.Start()) using (var agent = new AgentService(options: options, directoryAccessor: directoryAccessor)) diff --git a/MLS.Agent.Tests/WorkspaceDiscoveryTests.cs b/MLS.Agent.Tests/WorkspaceDiscoveryTests.cs index 57eb0258b..ae28d2bf4 100644 --- a/MLS.Agent.Tests/WorkspaceDiscoveryTests.cs +++ b/MLS.Agent.Tests/WorkspaceDiscoveryTests.cs @@ -36,7 +36,7 @@ public async Task Local_tool_workspace_can_be_discovered() var output = Guid.NewGuid().ToString(); var requestJson = Create.SimpleWorkspaceRequestAsJson(output, packageName); - var response = await CallRun(requestJson, options: new StartupOptions(addPackageSource: new PackageSource(packageLocation.FullName), dir: new DirectoryInfo(Directory.GetCurrentDirectory()))); + var response = await CallRun(requestJson, options: new StartupOptions(addPackageSource: new PackageSource(packageLocation.FullName), rootDirectory: new FileSystemDirectoryAccessor(Directory.GetCurrentDirectory()))); var result = await response .EnsureSuccess() .DeserializeAs(); diff --git a/MLS.Agent/CommandLine/CommandLineParser.cs b/MLS.Agent/CommandLine/CommandLineParser.cs index 702313ac8..1e7a62da4 100644 --- a/MLS.Agent/CommandLine/CommandLineParser.cs +++ b/MLS.Agent/CommandLine/CommandLineParser.cs @@ -7,9 +7,12 @@ using System.CommandLine.Invocation; using System.IO; using System.Linq; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.ComTypes; using System.Threading.Tasks; using Clockwise; using Microsoft.AspNetCore.Hosting; +using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.DotNet.Interactive; using Microsoft.DotNet.Interactive.Jupyter; using Microsoft.Extensions.DependencyInjection; @@ -93,11 +96,9 @@ public static Parser Create( new GitHubRepoLocator())); verify = verify ?? - ((verifyOptions, console, startupOptions) => - VerifyCommand.Do(verifyOptions, + ((options, console, startupOptions) => + VerifyCommand.Do(options, console, - () => new FileSystemDirectoryAccessor(verifyOptions.Dir), - PackageRegistry.CreateForTryMode(verifyOptions.Dir), startupOptions)); pack = pack ?? @@ -106,15 +107,30 @@ public static Parser Create( install = install ?? InstallCommand.Do; - startKernelServer = startKernelServer ?? + startKernelServer = startKernelServer ?? KernelServerCommand.Do; - var dirArgument = new Argument + var dirArgument = new Argument(() => new FileSystemDirectoryAccessor(Directory.GetCurrentDirectory())) { + Name = nameof(StartupOptions.RootDirectory), Arity = ArgumentArity.ZeroOrOne, - Name = nameof(StartupOptions.Dir).ToLower(), - Description = "Specify the path to the root directory for your documentation" - }.ExistingOnly(); + Description = "Specify the path to the root directory for your documentation", + }; + + dirArgument.AddValidator(symbolResult => + { + var directory = symbolResult.Tokens + .Select(t => t.Value) + .FirstOrDefault(); + + if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory)) + { + return $"Directory does not exist: {directory}"; + } + + return null; + }); + var rootCommand = StartInTryMode(); @@ -236,7 +252,7 @@ RootCommand StartInTryMode() command.Handler = CommandHandler.Create((context, options) => { services.AddSingleton(_ => PackageRegistry.CreateForTryMode( - options.Dir, + options.RootDirectory, options.AddPackageSource)); startServer(options, context); @@ -472,7 +488,7 @@ Command Verify() { var verifyCommand = new Command("verify", "Verify Markdown files in the target directory and its children.") { - dirArgument + dirArgument }; verifyCommand.Handler = CommandHandler.Create( @@ -498,4 +514,4 @@ private static CompositeKernel CreateKernel() }; } } -} +} \ No newline at end of file diff --git a/MLS.Agent/CommandLine/DemoCommand.cs b/MLS.Agent/CommandLine/DemoCommand.cs index 4d3292370..c4f5c6995 100644 --- a/MLS.Agent/CommandLine/DemoCommand.cs +++ b/MLS.Agent/CommandLine/DemoCommand.cs @@ -8,6 +8,7 @@ using System.IO.Compression; using System.Linq; using System.Threading.Tasks; +using WorkspaceServer; namespace MLS.Agent.CommandLine { @@ -61,7 +62,7 @@ public static Task Do( startServer?.Invoke(new StartupOptions( uri: new Uri("QuickStart.md", UriKind.Relative), - dir: options.Output), + rootDirectory: new FileSystemDirectoryAccessor(options.Output)), context); return Task.FromResult(0); diff --git a/MLS.Agent/CommandLine/StartupOptions.cs b/MLS.Agent/CommandLine/StartupOptions.cs index 7393833a0..556117101 100644 --- a/MLS.Agent/CommandLine/StartupOptions.cs +++ b/MLS.Agent/CommandLine/StartupOptions.cs @@ -36,7 +36,6 @@ public StartupOptions( string applicationInsightsKey = null, string id = null, string regionId = null, - DirectoryInfo dir = null, PackageSource addPackageSource = null, Uri uri = null, DirectoryInfo logPath = null, @@ -46,7 +45,8 @@ public StartupOptions( string packageVersion = null, ParseResult parseResult = null, ushort? port = null, - bool isJupyter = false) + bool isJupyter = false, + IDirectoryAccessor rootDirectory = null) { _parseResult = parseResult; LogPath = logPath; @@ -57,7 +57,7 @@ public StartupOptions( Key = key; ApplicationInsightsKey = applicationInsightsKey; RegionId = regionId; - Dir = dir ?? new DirectoryInfo(Directory.GetCurrentDirectory()); + RootDirectory = rootDirectory?? new FileSystemDirectoryAccessor(new DirectoryInfo(Directory.GetCurrentDirectory())); AddPackageSource = addPackageSource; Uri = uri; EnablePreviewFeatures = enablePreviewFeatures; @@ -71,7 +71,7 @@ public StartupOptions( public bool EnablePreviewFeatures { get; } public string Id { get; } public string RegionId { get; } - public DirectoryInfo Dir { get; } + public IDirectoryAccessor RootDirectory { get; } public PackageSource AddPackageSource { get; } public Uri Uri { get; set; } public bool Production { get; } @@ -99,7 +99,7 @@ public StartupMode Mode ? Environments.Production : Environments.Development; - public DirectoryInfo LogPath { get; } + public DirectoryInfo LogPath { get; } public bool Verbose { get; } diff --git a/MLS.Agent/CommandLine/VerifyCommand.cs b/MLS.Agent/CommandLine/VerifyCommand.cs index 693dc66a1..987a439f0 100644 --- a/MLS.Agent/CommandLine/VerifyCommand.cs +++ b/MLS.Agent/CommandLine/VerifyCommand.cs @@ -21,13 +21,12 @@ namespace MLS.Agent.CommandLine public static class VerifyCommand { public static async Task Do( - VerifyOptions options, + VerifyOptions verifyOptions, IConsole console, - Func getDirectoryAccessor, - PackageRegistry packageRegistry, StartupOptions startupOptions = null) { - var directoryAccessor = getDirectoryAccessor(); + var directoryAccessor = verifyOptions.RootDirectory; + var packageRegistry = PackageRegistry.CreateForTryMode(directoryAccessor); var markdownProject = new MarkdownProject( directoryAccessor, packageRegistry, diff --git a/MLS.Agent/CommandLine/VerifyOptions.cs b/MLS.Agent/CommandLine/VerifyOptions.cs index c1a49bae5..4b36c756a 100644 --- a/MLS.Agent/CommandLine/VerifyOptions.cs +++ b/MLS.Agent/CommandLine/VerifyOptions.cs @@ -2,16 +2,17 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System.IO; +using WorkspaceServer; namespace MLS.Agent.CommandLine { public class VerifyOptions { - public VerifyOptions(DirectoryInfo dir) + public VerifyOptions(IDirectoryAccessor rootDirectory) { - Dir = dir; + RootDirectory = rootDirectory ?? throw new System.ArgumentNullException(nameof(rootDirectory)); } - public DirectoryInfo Dir { get; } + public IDirectoryAccessor RootDirectory { get; } } } \ No newline at end of file diff --git a/MLS.Agent/Controllers/DocumentationController.cs b/MLS.Agent/Controllers/DocumentationController.cs index 05d72b7b7..933d9968f 100644 --- a/MLS.Agent/Controllers/DocumentationController.cs +++ b/MLS.Agent/Controllers/DocumentationController.cs @@ -229,7 +229,7 @@ private IHtmlContent Index(string html) => - dotnet try - {_startupOptions.Dir.FullName.HtmlEncode()} + dotnet try - {_startupOptions.RootDirectory.GetFullyQualifiedRoot().FullName.HtmlEncode()} @@ -250,7 +250,7 @@ private IHtmlContent Header() => $@"
Try .NET - {_startupOptions.Dir.FullName.ToLowerInvariant().HtmlEncode()} + {_startupOptions.RootDirectory.GetFullyQualifiedRoot().FullName.ToLowerInvariant().HtmlEncode()}
Powered by Try .NET
".ToHtmlContent(); diff --git a/MLS.Agent/Startup.cs b/MLS.Agent/Startup.cs index d22d01fd1..76086c175 100644 --- a/MLS.Agent/Startup.cs +++ b/MLS.Agent/Startup.cs @@ -92,7 +92,7 @@ public void ConfigureServices(IServiceCollection services) case StartupMode.Try: return PackageRegistry.CreateForTryMode( - StartupOptions.Dir, + StartupOptions.RootDirectory, StartupOptions.AddPackageSource); default: @@ -126,8 +126,7 @@ public void ConfigureServices(IServiceCollection services) } else { - return new FileSystemDirectoryAccessor(StartupOptions.Dir ?? - new DirectoryInfo(Directory.GetCurrentDirectory())); + return StartupOptions.RootDirectory; } }); diff --git a/Microsoft.DotNet.Try.ProjectTemplate.Tests/TutorialTemplateTests.cs b/Microsoft.DotNet.Try.ProjectTemplate.Tests/TutorialTemplateTests.cs index d41bdb556..128c6f4f3 100644 --- a/Microsoft.DotNet.Try.ProjectTemplate.Tests/TutorialTemplateTests.cs +++ b/Microsoft.DotNet.Try.ProjectTemplate.Tests/TutorialTemplateTests.cs @@ -46,13 +46,10 @@ public async Task When_the_template_is_installed_verify_works() //The template targets 3.0 hence verify should run against 3.0 and not 2.1.503 used in the solution directory await dotnet.New("global.json", "--sdk-version 3.0.100-preview6-012264"); var console = new TestConsole(); - var directoryAccessor = new FileSystemDirectoryAccessor(outputDirectory); var resultCode = await VerifyCommand.Do( - new VerifyOptions(outputDirectory), - console, - () => directoryAccessor, - PackageRegistry.CreateForTryMode(outputDirectory)); + new VerifyOptions(new FileSystemDirectoryAccessor(outputDirectory)), + console); console.Out .ToString() diff --git a/WorkspaceServer.Tests/RebuildablePackageTests.cs b/WorkspaceServer.Tests/RebuildablePackageTests.cs index bc473ad89..99b7cbb02 100644 --- a/WorkspaceServer.Tests/RebuildablePackageTests.cs +++ b/WorkspaceServer.Tests/RebuildablePackageTests.cs @@ -44,6 +44,44 @@ public async Task If_a_new_file_is_added_the_workspace_includes_the_file() ws.CurrentSolution.Projects.First().Documents.Select(d => d.FilePath).Should().Contain(filePath => filePath == newFile); } + [Fact] + public async Task If_an_already_built_package_contains_new_file_the_new_workspace_contains_the_file() + { + var oldPackage = await Create.ConsoleWorkspaceCopy(isRebuildable:true); + var ws = await oldPackage.CreateRoslynWorkspaceForRunAsync(new TimeBudget(30.Seconds())); + + var newFile = Path.Combine(oldPackage.Directory.FullName, "Sample.cs"); + ws.CurrentSolution.Projects.First().Documents.Select(d => d.FilePath).Should().NotContain(filePath => filePath == newFile); + + File.WriteAllText(newFile, "//this is a new file"); + + var newPackage = new RebuildablePackage(directory: oldPackage.Directory); + ws = await newPackage.CreateRoslynWorkspaceForRunAsync(new TimeBudget(30.Seconds())); + + ws.CurrentSolution.Projects.First().Documents.Select(d => d.FilePath).Should().Contain(filePath => filePath == newFile); + } + + [Fact] + public async Task If_an_already_built_package_contains_a_new_file_and_an_old_file_is_deleted_workspace_reflects_it() + { + var oldPackage = await Create.ConsoleWorkspaceCopy(isRebuildable: true); + + var sampleCsFile = Path.Combine(oldPackage.Directory.FullName, "Sample.cs"); + File.WriteAllText(sampleCsFile, "//this is a file which will be deleted later"); + var ws = await oldPackage.CreateRoslynWorkspaceForRunAsync(new TimeBudget(30.Seconds())); + ws.CurrentSolution.Projects.First().Documents.Select(d => d.FilePath).Should().Contain(filePath => filePath == sampleCsFile); + + File.Delete(sampleCsFile); + var newFileAdded = Path.Combine(oldPackage.Directory.FullName, "foo.cs"); + File.WriteAllText(newFileAdded, "//this is a file we have just created"); + + var newPackage = new RebuildablePackage(directory: oldPackage.Directory); + ws = await newPackage.CreateRoslynWorkspaceForRunAsync(new TimeBudget(30.Seconds())); + + ws.CurrentSolution.Projects.First().Documents.Select(d => d.FilePath).Should().NotContain(filePath => filePath == sampleCsFile); + ws.CurrentSolution.Projects.First().Documents.Select(d => d.FilePath).Should().Contain(filePath => filePath == newFileAdded); + } + [Fact] public async Task If_the_project_file_is_changed_then_the_workspace_reflects_the_changes() { diff --git a/WorkspaceServer/FileSystemDirectoryAccessor.cs b/WorkspaceServer/FileSystemDirectoryAccessor.cs index db8ce597b..e9678d016 100644 --- a/WorkspaceServer/FileSystemDirectoryAccessor.cs +++ b/WorkspaceServer/FileSystemDirectoryAccessor.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Text; using System.Threading.Tasks; using Microsoft.DotNet.Try.Markdown; using WorkspaceServer.Packaging; @@ -16,6 +17,10 @@ public class FileSystemDirectoryAccessor : IDirectoryAccessor { private readonly DirectoryInfo _rootDirectory; + public FileSystemDirectoryAccessor(string directory): this(new DirectoryInfo(directory)) + { + } + public FileSystemDirectoryAccessor(DirectoryInfo rootDir) { _rootDirectory = rootDir ?? throw new ArgumentNullException(nameof(rootDir)); diff --git a/WorkspaceServer/PackageRegistry.cs b/WorkspaceServer/PackageRegistry.cs index dd6da7855..ea3e7d810 100644 --- a/WorkspaceServer/PackageRegistry.cs +++ b/WorkspaceServer/PackageRegistry.cs @@ -157,7 +157,7 @@ private Task GetPackageFromPackageBuilder(string packageName, Budget b }); } - public static PackageRegistry CreateForTryMode(DirectoryInfo project, PackageSource addSource = null) + public static PackageRegistry CreateForTryMode(IDirectoryAccessor projectDirectory, PackageSource addSource = null) { var finders = GetDefaultPackageFinders().Append(new PackageInstallingWebAssemblyAssetFinder(new FileSystemDirectoryAccessor(Package.DefaultPackagesDirectory), addSource)); var registry = new PackageRegistry( @@ -166,10 +166,12 @@ public static PackageRegistry CreateForTryMode(DirectoryInfo project, PackageSou finders, additionalStrategies: new LocalToolInstallingPackageDiscoveryStrategy(Package.DefaultPackagesDirectory, addSource)); - registry.Add(project.Name, builder => + var directory = projectDirectory.GetFullyQualifiedRoot(); + + registry.Add(directory.Name, builder => { builder.CreateRebuildablePackage = true; - builder.Directory = project; + builder.Directory = directory; }); return registry; diff --git a/WorkspaceServer/Packaging/RebuildablePackage.cs b/WorkspaceServer/Packaging/RebuildablePackage.cs index 7e7427472..8230d2290 100644 --- a/WorkspaceServer/Packaging/RebuildablePackage.cs +++ b/WorkspaceServer/Packaging/RebuildablePackage.cs @@ -7,6 +7,7 @@ using System.Reactive.Concurrency; using System.Runtime.CompilerServices; using System.Threading.Tasks; +using Buildalyzer.Workspaces; using Clockwise; namespace WorkspaceServer.Packaging @@ -18,6 +19,10 @@ public class RebuildablePackage : Package public RebuildablePackage(string name = null, IPackageInitializer initializer = null, DirectoryInfo directory = null, IScheduler buildThrottleScheduler = null) : base(name, initializer, directory, buildThrottleScheduler) { + if (BuildResultNeedsUpdate()) + { + Reset(); + } } void SetupFileWatching() @@ -134,5 +139,18 @@ private void FileSystemWatcherOnChangedOrDeleted(object sender, FileSystemEventA { HandleFileChanges(e.Name); } + + private bool BuildResultNeedsUpdate() + { + if (DesignTimeBuildResult != null) + { + var filesInDirectory = Directory.GetFiles("*.cs", SearchOption.AllDirectories).Select(file => file.FullName); + var documentsInLastBuild = DesignTimeBuildResult.GetWorkspace().CurrentSolution.Projects.First().Documents.Select(document => document.FilePath); + + return filesInDirectory.Count() != documentsInLastBuild.Count() || !documentsInLastBuild.All(filesInDirectory.Contains); + } + + return true; + } } }