public override sealed async Task <int> ExecuteCommandAsync(CommandContext commandContext, TSettings commandSettings)
        {
            // We need to get the engine command settings to pass to the engine manager
            // First try the actual command settings
            if (!(commandSettings is EngineCommandSettings engineCommandSettings))
            {
                // Then try the command data or create one and either way copy over the base command settings
                engineCommandSettings          = commandContext.Data as EngineCommandSettings ?? new EngineCommandSettings();
                engineCommandSettings.LogLevel = commandSettings.LogLevel;
                engineCommandSettings.Attach   = commandSettings.Attach;
                engineCommandSettings.LogFile  = commandSettings.LogFile;
            }

            // Execute the engine manager and dispose it when done
            using (EngineManager engineManager =
                       new EngineManager(
                           commandContext,
                           engineCommandSettings,
                           EngineSettings,
                           ConfigurationRoot,
                           ServiceCollection,
                           Bootstrapper))
            {
                return(await ExecuteEngineAsync(commandContext, commandSettings, engineManager));
            }
        }
Exemplo n.º 2
0
        public override async Task <int> ExecuteCommandAsync(IServiceCollection serviceCollection, CommandContext context, Settings settings)
        {
            CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();

            using (EngineManager engineManager = new EngineManager(serviceCollection, _configurators, settings))
            {
                return(await engineManager.ExecuteAsync(cancellationTokenSource)
                    ? (int)ExitCode.Normal
                    : (int)ExitCode.ExecutionError);
            }
        }
Exemplo n.º 3
0
        public override async Task <int> ExecuteCommandAsync(IServiceCollection serviceCollection, CommandContext context, Settings settings)
        {
            ExitCode exitCode = ExitCode.Normal;

            using (EngineManager engineManager = new EngineManager(serviceCollection, _configurators, settings))
            {
                ILogger logger = engineManager.Engine.Services.GetRequiredService <ILogger <Bootstrapper> >();

                // Execute the engine for the first time
                CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
                if (!await engineManager.ExecuteAsync(cancellationTokenSource))
                {
                    return((int)ExitCode.ExecutionError);
                }

                // Start the preview server
                Dictionary <string, string> contentTypes = settings.ContentTypes?.Length > 0
                    ? GetContentTypes(settings.ContentTypes)
                    : new Dictionary <string, string>();
                ILoggerProvider loggerProvider = engineManager.Engine.Services.GetRequiredService <ILoggerProvider>();
                Server          previewServer  = await StartPreviewServerAsync(
                    engineManager.Engine.FileSystem.GetOutputDirectory().Path,
                    settings.Port,
                    settings.ForceExt,
                    settings.VirtualDirectory,
                    !settings.NoReload,
                    contentTypes,
                    loggerProvider,
                    logger);

                // Start the watchers
                ActionFileSystemWatcher inputFolderWatcher = null;
                if (!settings.NoWatch)
                {
                    logger.LogInformation("Watching paths(s) {0}", string.Join(", ", engineManager.Engine.FileSystem.InputPaths));
                    inputFolderWatcher = new ActionFileSystemWatcher(
                        engineManager.Engine.FileSystem.GetOutputDirectory().Path,
                        engineManager.Engine.FileSystem.GetInputDirectories().Select(x => x.Path),
                        true,
                        "*.*",
                        path =>
                    {
                        _changedFiles.Enqueue(path);
                        _messageEvent.Set();
                    });
                }

                // Start the message pump

                // Only wait for a key if console input has not been redirected, otherwise it's on the caller to exit
                if (!Console.IsInputRedirected)
                {
                    // Start the key listening thread
                    Thread thread = new Thread(() =>
                    {
                        logger.LogInformation("Hit Ctrl-C to exit");
                        Console.TreatControlCAsInput = true;
                        while (true)
                        {
                            // Would have preferred to use Console.CancelKeyPress, but that bubbles up to calling batch files
                            // The (ConsoleKey)3 check is to support a bug in VS Code: https://github.com/Microsoft/vscode/issues/9347
                            ConsoleKeyInfo consoleKey = Console.ReadKey(true);
                            if (consoleKey.Key == (ConsoleKey)3 || (consoleKey.Key == ConsoleKey.C && (consoleKey.Modifiers & ConsoleModifiers.Control) != 0))
                            {
                                _exit.Set();
                                _messageEvent.Set();
                                break;
                            }
                        }
                    })
                    {
                        IsBackground = true
                    };
                    thread.Start();
                }

                // Wait for activity
                while (true)
                {
                    _messageEvent.WaitOne(); // Blocks the current thread until a signal
                    if (_exit)
                    {
                        break;
                    }

                    // Execute if files have changed
                    HashSet <string> changedFiles = new HashSet <string>();
                    while (_changedFiles.TryDequeue(out string changedFile))
                    {
                        if (changedFiles.Add(changedFile))
                        {
                            logger.LogDebug($"{changedFile} has changed");
                        }
                    }
                    if (changedFiles.Count > 0)
                    {
                        logger.LogInformation($"{changedFiles.Count} files have changed, re-executing");

                        // Reset caches when an error occurs during the previous preview
                        object existingResetCacheSetting = null;
                        bool   setResetCacheSetting      = false;
                        if (exitCode == ExitCode.ExecutionError)
                        {
                            existingResetCacheSetting = engineManager.Engine.Settings.GetValueOrDefault(Keys.ResetCache);
                            setResetCacheSetting      = true;
                            engineManager.Engine.Settings[Keys.ResetCache] = true;
                        }

                        // If there was an execution error due to reload, keep previewing but clear the cache
                        cancellationTokenSource = new CancellationTokenSource();
                        exitCode = await engineManager.ExecuteAsync(cancellationTokenSource)
                            ? ExitCode.Normal
                            : ExitCode.ExecutionError;

                        // Reset the reset cache setting after removing it
                        if (setResetCacheSetting)
                        {
                            if (existingResetCacheSetting == null)
                            {
                                engineManager.Engine.Settings.Remove(Keys.ResetCache);
                            }
                            {
                                engineManager.Engine.Settings[Keys.ResetCache] = existingResetCacheSetting;
                            }
                        }

                        await previewServer.TriggerReloadAsync();
                    }

                    // Check one more time for exit
                    if (_exit)
                    {
                        break;
                    }
                    logger.LogInformation("Hit Ctrl-C to exit");
                    _messageEvent.Reset();
                }

                // Shutdown
                logger.LogInformation("Shutting down");
                inputFolderWatcher?.Dispose();
                previewServer.Dispose();
            }

            return((int)exitCode);
        }