public void ThrowsWhenRootDoesNotExist() { var files = new TemporaryFileProvider(); var finder = new MsBuildProjectFinder(files.Root); files.Dispose(); Assert.Throws <FileNotFoundException>(() => finder.FindMsBuildProject(null)); }
public void ThrowsWhenFileDoesNotExist() { using (var files = new TemporaryFileProvider()) { var finder = new MsBuildProjectFinder(files.Root); Assert.Throws <FileNotFoundException>(() => finder.FindMsBuildProject("test.csproj")); } }
public void ThrowsWhenNoFile() { using (var files = new TemporaryFileProvider()) { var finder = new MsBuildProjectFinder(files.Root); Assert.Throws <InvalidOperationException>(() => finder.FindMsBuildProject()); } }
public void ThrowsWhenNoFile() { using (var files = new TemporaryFileProvider()) { var finder = new MsBuildProjectFinder(files.Root); Assert.Throws <FileNotFoundException>(() => finder.FindMsBuildProject(null)); } }
public void DoesNotMatchXproj() { using (var files = new TemporaryFileProvider()) { var finder = new MsBuildProjectFinder(files.Root); files.Add("test.xproj", ""); Assert.Throws <FileNotFoundException>(() => finder.FindMsBuildProject(null)); } }
public void ThrowsWhenMultipleFile() { using (var files = new TemporaryFileProvider()) { files.Add("Test1.csproj", ""); files.Add("Test2.csproj", ""); var finder = new MsBuildProjectFinder(files.Root); Assert.Throws <FileNotFoundException>(() => finder.FindMsBuildProject(null)); } }
public void FindsSingleProject(string extension) { using (var files = new TemporaryFileProvider()) { var filename = "TestProject" + extension; files.Add(filename, ""); var finder = new MsBuildProjectFinder(files.Root); Assert.Equal(Path.Combine(files.Root, filename), finder.FindMsBuildProject(null)); } }
private async Task <int> ListFilesAsync( IReporter reporter, string project, CancellationToken cancellationToken) { // TODO multiple projects should be easy enough to add here string projectFile; try { projectFile = MsBuildProjectFinder.FindMsBuildProject(_workingDirectory, project); } catch (FileNotFoundException ex) { reporter.Error(ex.Message); return(1); } var fileSetFactory = new MsBuildFileSetFactory(reporter, DotNetWatchOptions.Default, projectFile, waitOnError: false, trace: false); var files = await fileSetFactory.CreateAsync(cancellationToken); if (files == null) { return(1); } foreach (var group in files.GroupBy(g => g.FileKind).OrderBy(g => g.Key)) { if (group.Key == FileKind.StaticFile) { _console.Out.WriteLine("::: Watch Action: Refresh browser :::"); } foreach (var file in group) { if (file.FileKind == FileKind.StaticFile) { _console.Out.WriteLine($"{file.FilePath} ~/{file.StaticWebAssetPath}"); } else { _console.Out.WriteLine(file.FilePath); } } } return(0); }
private async Task <int> MainInternalAsync( IReporter reporter, string project, IReadOnlyCollection <string> args, CancellationToken cancellationToken) { // TODO multiple projects should be easy enough to add here string projectFile; try { projectFile = MsBuildProjectFinder.FindMsBuildProject(_workingDirectory, project); } catch (FileNotFoundException ex) { reporter.Error(ex.Message); return(1); } var watchOptions = DotNetWatchOptions.Default; var fileSetFactory = new MsBuildFileSetFactory(reporter, watchOptions, projectFile, waitOnError: true, trace: false); var processInfo = new ProcessSpec { Executable = new Muxer().MuxerPath, WorkingDirectory = Path.GetDirectoryName(projectFile), Arguments = args, EnvironmentVariables = { ["DOTNET_WATCH"] = "1" }, }; if (CommandLineOptions.IsPollingEnabled) { _reporter.Output("Polling file watcher is enabled"); } await using var watcher = new DotNetWatcher(reporter, fileSetFactory, watchOptions); await watcher.WatchAsync(processInfo, cancellationToken); return(0); }
private async Task <int> ListFilesAsync( IReporter reporter, string project, CancellationToken cancellationToken) { // TODO multiple projects should be easy enough to add here string projectFile; try { projectFile = MsBuildProjectFinder.FindMsBuildProject(_workingDirectory, project); } catch (FileNotFoundException ex) { reporter.Error(ex.Message); return(1); } var fileSetFactory = new MsBuildFileSetFactory( reporter, DotNetWatchOptions.Default, projectFile, waitOnError: false, trace: false); var files = await fileSetFactory.CreateAsync(cancellationToken); if (files == null) { return(1); } foreach (var file in files) { _console.Out.WriteLine(file.FilePath); } return(0); }
private async Task <int> MainInternalAsync( IReporter reporter, string project, IReadOnlyList <string> args, CancellationToken cancellationToken) { // TODO multiple projects should be easy enough to add here string projectFile; try { projectFile = MsBuildProjectFinder.FindMsBuildProject(_workingDirectory, project); } catch (FileNotFoundException ex) { reporter.Error(ex.Message); return(1); } var isDefaultRunCommand = false; if (args.Count == 1 && args[0] == "run") { isDefaultRunCommand = true; } else if (args.Count == 0) { isDefaultRunCommand = true; args = new[] { "run" }; } var watchOptions = DotNetWatchOptions.Default; var fileSetFactory = new MsBuildFileSetFactory(reporter, watchOptions, projectFile, waitOnError: true, trace: false); var processInfo = new ProcessSpec { Executable = DotnetMuxer.MuxerPath, WorkingDirectory = Path.GetDirectoryName(projectFile), Arguments = args, EnvironmentVariables = { ["DOTNET_WATCH"] = "1" }, }; if (CommandLineOptions.IsPollingEnabled) { _reporter.Output("Polling file watcher is enabled"); } var defaultProfile = LaunchSettingsProfile.ReadDefaultProfile(_workingDirectory, reporter); var context = new DotNetWatchContext { ProcessSpec = processInfo, Reporter = _reporter, SuppressMSBuildIncrementalism = watchOptions.SuppressMSBuildIncrementalism, DefaultLaunchSettingsProfile = defaultProfile, }; if (isDefaultRunCommand && !string.IsNullOrEmpty(defaultProfile?.HotReloadProfile)) { _reporter.Verbose($"Found HotReloadProfile={defaultProfile.HotReloadProfile}. Watching with hot-reload"); // We'll sue hot-reload based watching if // a) watch was invoked with no args or with exactly one arg - the run command e.g. `dotnet watch` or `dotnet watch run` // b) The launch profile supports hot-reload based watching. // The watcher will complain if users configure this for runtimes that would not support it. await using var watcher = new HotReloadDotNetWatcher(reporter, fileSetFactory, watchOptions, _console); await watcher.WatchAsync(context, cancellationToken); } else { _reporter.Verbose("Did not find a HotReloadProfile or running a non-default command. Watching with legacy behavior."); // We'll use the presence of a profile to decide if we're going to use the hot-reload based watching. // The watcher will complain if users configure this for runtimes that would not support it. await using var watcher = new DotNetWatcher(reporter, fileSetFactory, watchOptions); await watcher.WatchAsync(context, cancellationToken); } return(0); }
public string Resolve(string project, string configuration) { var finder = new MsBuildProjectFinder(_workingDirectory); string projectFile; try { projectFile = finder.FindMsBuildProject(project); } catch (Exception ex) { _reporter.Error(ex.Message); return(null); } _reporter.Verbose(SecretsHelpersResources.FormatMessage_Project_File_Path(projectFile)); configuration = !string.IsNullOrEmpty(configuration) ? configuration : DefaultConfig; var outputFile = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); try { var psi = new ProcessStartInfo { FileName = DotNetMuxer.MuxerPathOrDefault(), RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, ArgumentList = { "msbuild", projectFile, "/nologo", "/t:_ExtractUserSecretsMetadata", // defined in SecretManager.targets "/p:_UserSecretsMetadataFile=" + outputFile, "/p:Configuration=" + configuration, "/p:CustomAfterMicrosoftCommonTargets=" + _targetsFile, "/p:CustomAfterMicrosoftCommonCrossTargetingTargets=" + _targetsFile, "-verbosity:detailed", } }; #if DEBUG _reporter.Verbose($"Invoking '{psi.FileName} {psi.Arguments}'"); #endif using var process = new Process() { StartInfo = psi, }; var outputBuilder = new StringBuilder(); var errorBuilder = new StringBuilder(); process.OutputDataReceived += (_, d) => { if (!string.IsNullOrEmpty(d.Data)) { outputBuilder.AppendLine(d.Data); } }; process.ErrorDataReceived += (_, d) => { if (!string.IsNullOrEmpty(d.Data)) { errorBuilder.AppendLine(d.Data); } }; process.Start(); process.BeginOutputReadLine(); process.BeginErrorReadLine(); process.WaitForExit(); if (process.ExitCode != 0) { _reporter.Verbose(outputBuilder.ToString()); _reporter.Verbose(errorBuilder.ToString()); _reporter.Error($"Exit code: {process.ExitCode}"); _reporter.Error(SecretsHelpersResources.FormatError_ProjectFailedToLoad(projectFile)); return(null); } if (!File.Exists(outputFile)) { _reporter.Error(SecretsHelpersResources.FormatError_ProjectMissingId(projectFile)); return(null); } var id = File.ReadAllText(outputFile)?.Trim(); if (string.IsNullOrEmpty(id)) { _reporter.Error(SecretsHelpersResources.FormatError_ProjectMissingId(projectFile)); } return(id); } finally { TryDelete(outputFile); } }
private static string ResolveProjectPath(string name, string path) { var finder = new MsBuildProjectFinder(path); return(finder.FindMsBuildProject(name)); }
private async Task <int> MainInternalAsync(CommandLineOptions options, CancellationToken cancellationToken) { // TODO multiple projects should be easy enough to add here string projectFile; try { projectFile = MsBuildProjectFinder.FindMsBuildProject(_workingDirectory, options.Project); } catch (FileNotFoundException ex) { _reporter.Error(ex.Message); return(1); } var args = options.RemainingArguments; var isDefaultRunCommand = false; if (args.Count == 1 && args[0] == "run") { isDefaultRunCommand = true; } else if (args.Count == 0) { isDefaultRunCommand = true; args = new[] { "run" }; } var watchOptions = DotNetWatchOptions.Default; watchOptions.NonInteractive = options.NonInteractive; var fileSetFactory = new MsBuildFileSetFactory(_reporter, watchOptions, projectFile, waitOnError: true, trace: false); var processInfo = new ProcessSpec { Executable = DotnetMuxer.MuxerPath, WorkingDirectory = Path.GetDirectoryName(projectFile), Arguments = args, EnvironmentVariables = { ["DOTNET_WATCH"] = "1" }, }; if (CommandLineOptions.IsPollingEnabled) { _reporter.Output("Polling file watcher is enabled"); } var defaultProfile = LaunchSettingsProfile.ReadDefaultProfile(processInfo.WorkingDirectory, _reporter) ?? new(); var context = new DotNetWatchContext { ProcessSpec = processInfo, Reporter = _reporter, SuppressMSBuildIncrementalism = watchOptions.SuppressMSBuildIncrementalism, DefaultLaunchSettingsProfile = defaultProfile, }; context.ProjectGraph = TryReadProject(projectFile); if (!options.NoHotReload && isDefaultRunCommand && context.ProjectGraph is not null && IsHotReloadSupported(context.ProjectGraph)) { _reporter.Verbose($"Project supports hot reload and was configured to run with the default run-command. Watching with hot-reload"); // Use hot-reload based watching if // a) watch was invoked with no args or with exactly one arg - the run command e.g. `dotnet watch` or `dotnet watch run` // b) The launch profile supports hot-reload based watching. // The watcher will complain if users configure this for runtimes that would not support it. await using var watcher = new HotReloadDotNetWatcher(_reporter, _requester, fileSetFactory, watchOptions, _console, _workingDirectory); await watcher.WatchAsync(context, cancellationToken); }
private async Task <int> RunCoreAsync(CommandLineOptions options) { string projectFilePath; try { projectFilePath = MsBuildProjectFinder.FindMsBuildProject(_workingDir, options.Project); } catch (FileNotFoundException ex) { _reporter.Error(ex.Message); return(1); } var projectDirPath = Path.GetDirectoryName(projectFilePath); string configFilePath; if (options.ConfigSources.HasFlag(ConfigSources.ConfigFile)) { configFilePath = options.ConfigFile ?? GetDefaultConfigFilePath(projectDirPath); } else { configFilePath = null; } string compilationBasePath; IEnumerable <string> assemblyFilePaths; if (options.ConfigSources.HasFlag(ConfigSources.AppAssembly) || options.ConfigSources.HasFlag(ConfigSources.OutputAssemblies)) { var targetFilePath = options.BuildTargetPath; if (targetFilePath == null) { _reporter.Output($"Building project {projectFilePath}..."); targetFilePath = await new MsBuildEnsureBuildTarget(_reporter, projectFilePath).ExecuteAsync(options.BuildConfiguration, _cts.Token); // we need the project to be built if configuration is specified by code if (targetFilePath == null) { return(1); } } compilationBasePath = Path.GetDirectoryName(targetFilePath); if (options.ConfigSources.HasFlag(ConfigSources.OutputAssemblies)) { assemblyFilePaths = Directory.EnumerateFiles(compilationBasePath, "*.dll", SearchOption.TopDirectoryOnly); } else { assemblyFilePaths = Enumerable.Empty <string>(); } if (options.ConfigSources.HasFlag(ConfigSources.AppAssembly)) { assemblyFilePaths = assemblyFilePaths.Prepend(targetFilePath); } assemblyFilePaths = assemblyFilePaths.Distinct(); } else { if (options.BuildTargetPath == null) { // TODO: prefer release build? compilationBasePath = Directory.EnumerateFiles(projectDirPath, BundleBuilderProxy.BundlingAssemblyName + ".dll", SearchOption.AllDirectories).FirstOrDefault(); if (compilationBasePath != null) { compilationBasePath = Path.GetDirectoryName(compilationBasePath); } } else { compilationBasePath = Path.GetDirectoryName(options.BuildTargetPath); } assemblyFilePaths = Enumerable.Empty <string>(); } // we load the application into a separate AssemblyLoadContext (to avoid assembly version mismatches), // then we pass the discovered bundling configurations to the design-time bundle builder implementation residing in the main assembly var assemblyLoader = new AssemblyLoader(compilationBasePath); var bundleBuilderProxy = new BundleBuilderProxy(assemblyLoader, _reporter); var settings = new Dictionary <string, object>(StringComparer.OrdinalIgnoreCase) { ["ProjectFilePath"] = projectFilePath, ["CompilationBasePath"] = compilationBasePath, ["Mode"] = options.Mode.ToString(), ["Logger"] = new Action <int, string>(Log) }; if (configFilePath != null) { settings["ConfigFilePath"] = configFilePath; } await bundleBuilderProxy.ProcessConfigurationsAsync(assemblyFilePaths, settings, _cts.Token); return(0); }