public ProcessState(Process process, IReporter reporter) { _reporter = reporter; _process = process; _process.Exited += OnExited; Task = _tcs.Task.ContinueWith(_ => { try { // We need to use two WaitForExit calls to ensure that all of the output/events are processed. Previously // this code used Process.Exited, which could result in us missing some output due to the ordering of // events. // // See the remarks here: https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.process.waitforexit#System_Diagnostics_Process_WaitForExit_System_Int32_ if (!_process.WaitForExit(Int32.MaxValue)) { throw new TimeoutException(); } _process.WaitForExit(); } catch (InvalidOperationException) { // suppress if this throws if no process is associated with this object anymore. } }); }
public MsBuildFileSetFactory( IReporter reporter, string projectFile, bool waitOnError, bool trace) : this(new Muxer().MuxerPath, reporter, projectFile, new OutputSink(), waitOnError, trace) { }
public MsBuildFileSetFactory( IReporter reporter, DotNetWatchOptions dotNetWatchOptions, string projectFile, bool waitOnError, bool trace) : this(dotNetWatchOptions, DotnetMuxer.MuxerPath, reporter, projectFile, new OutputSink(), waitOnError, trace) { }
public Program(IConsole console, string workingDirectory) { Ensure.NotNull(console, nameof(console)); Ensure.NotNullOrEmpty(workingDirectory, nameof(workingDirectory)); _console = console; _workingDirectory = workingDirectory; _cts = new CancellationTokenSource(); console.CancelKeyPress += OnCancelKeyPress; _reporter = CreateReporter(verbose: true, quiet: false, console: _console); }
public HotReloadDotNetWatcher(IReporter reporter, IFileSetFactory fileSetFactory, DotNetWatchOptions dotNetWatchOptions, IConsole console) { Ensure.NotNull(reporter, nameof(reporter)); _reporter = reporter; _processRunner = new ProcessRunner(reporter); _dotNetWatchOptions = dotNetWatchOptions; _console = console; _filters = new IWatchFilter[] { new MSBuildEvaluationFilter(fileSetFactory), new DotNetBuildFilter(_processRunner, _reporter), new LaunchBrowserFilter(_dotNetWatchOptions), }; }
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); }
public HotReloadDotNetWatcher(IReporter reporter, IFileSetFactory fileSetFactory, DotNetWatchOptions dotNetWatchOptions, IConsole console) { Ensure.NotNull(reporter, nameof(reporter)); _reporter = reporter; _processRunner = new ProcessRunner(reporter); _dotNetWatchOptions = dotNetWatchOptions; _console = console; _filters = new IWatchFilter[] { new DotNetBuildFilter(fileSetFactory, _processRunner, _reporter), new LaunchBrowserFilter(dotNetWatchOptions), new BrowserRefreshFilter(dotNetWatchOptions, _reporter), }; _rudeEditDialog = new(reporter, _console); }
// output sink is for testing internal MsBuildFileSetFactory( string muxerPath, IReporter reporter, string projectFile, OutputSink outputSink, bool waitOnError, bool trace) { Ensure.NotNull(reporter, nameof(reporter)); Ensure.NotNullOrEmpty(projectFile, nameof(projectFile)); Ensure.NotNull(outputSink, nameof(outputSink)); _muxerPath = muxerPath; _reporter = reporter; _projectFile = projectFile; _outputSink = outputSink; _processRunner = new ProcessRunner(reporter); _buildFlags = InitializeArgs(FindTargetsFile(), trace); _waitOnError = waitOnError; }
private async Task <int> HandleWatch(CommandLineOptions options) { // update reporter as configured by options _reporter = CreateReporter(options.Verbose, options.Quiet, _console); try { if (_cts.IsCancellationRequested) { return(1); } if (options.List) { return(await ListFilesAsync(_reporter, options.Project, _cts.Token)); } else { return(await MainInternalAsync(_reporter, options.Project, options.RemainingArguments, _cts.Token)); } } catch (Exception ex) { if (ex is TaskCanceledException || ex is OperationCanceledException) { // swallow when only exception is the CTRL+C forced an exit return(0); } _reporter.Error(ex.ToString()); _reporter.Error("An unexpected error occurred"); return(1); } }
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); }
public HotReloadDotNetWatcher(IReporter reporter, IRequester requester, IFileSetFactory fileSetFactory, DotNetWatchOptions dotNetWatchOptions, IConsole console, string workingDirectory) { Ensure.NotNull(reporter, nameof(reporter)); Ensure.NotNull(requester, nameof(requester)); Ensure.NotNullOrEmpty(workingDirectory, nameof(workingDirectory)); _reporter = reporter; _processRunner = new ProcessRunner(reporter); _dotNetWatchOptions = dotNetWatchOptions; _console = console; _workingDirectory = workingDirectory; _filters = new IWatchFilter[] { new DotNetBuildFilter(fileSetFactory, _processRunner, _reporter), new LaunchBrowserFilter(dotNetWatchOptions), new BrowserRefreshFilter(dotNetWatchOptions, _reporter), }; if (!dotNetWatchOptions.NonInteractive) { _rudeEditDialog = new(reporter, requester, _console); } }
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 = new Muxer().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 ProcessRunner(IReporter reporter) { Ensure.NotNull(reporter, nameof(reporter)); _reporter = reporter; }