Ejemplo n.º 1
0
        protected override ExitCode RunCommand(Preprocessor preprocessor)
        {
            // Get the standard input stream
            _configOptions.Stdin = StandardInputReader.Read();

            // Fix the root folder and other files
            DirectoryPath currentDirectory = Environment.CurrentDirectory;

            _configOptions.RootPath       = _configOptions.RootPath == null ? currentDirectory : currentDirectory.Combine(_configOptions.RootPath);
            _logFilePath                  = _logFilePath == null ? null : _configOptions.RootPath.CombineFile(_logFilePath);
            _configOptions.ConfigFilePath = _configOptions.RootPath.CombineFile(_configOptions.ConfigFilePath ?? "config.wyam");

            // Set up the log file
            if (_logFilePath != null)
            {
                // Delete an exiting log file if one exists
                if (File.Exists(_logFilePath.FullPath))
                {
                    try
                    {
                        File.Delete(_logFilePath.FullPath);
                    }
                    catch (Exception)
                    {
                    }
                }

                Trace.AddListener(new SimpleFileTraceListener(_logFilePath.FullPath));
            }

            // Get the engine and configurator
            EngineManager engineManager = EngineManager.Get(preprocessor, _configOptions);

            if (engineManager == null)
            {
                return(ExitCode.CommandLineError);
            }

            // Configure and execute
            if (!engineManager.Configure())
            {
                return(ExitCode.ConfigurationError);
            }

            if (_verifyConfig)
            {
                Trace.Information("No errors. Exiting.");
                return(ExitCode.Normal);
            }

            TraceEnviornment(engineManager);

            if (!engineManager.Execute())
            {
                return(ExitCode.ExecutionError);
            }

            bool messagePump = false;

            // Start the preview server
            Server previewServer = null;

            if (_preview)
            {
                messagePump = true;
                DirectoryPath previewPath = _previewRoot == null
                    ? engineManager.Engine.FileSystem.GetOutputDirectory().Path
                    : engineManager.Engine.FileSystem.GetOutputDirectory(_previewRoot).Path;

                previewServer = PreviewServer.Start(previewPath, _previewPort, _previewForceExtension, _previewVirtualDirectory, _watch && !_noReload, _contentTypes);
            }

            // Start the watchers
            IDisposable inputFolderWatcher = null;
            IDisposable configFileWatcher  = null;

            if (_watch)
            {
                messagePump = true;

                Trace.Information("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();
                });

                if (_configOptions.ConfigFilePath != null)
                {
                    Trace.Information("Watching configuration file {0}", _configOptions.ConfigFilePath);
                    configFileWatcher = new ActionFileSystemWatcher(
                        engineManager.Engine.FileSystem.GetOutputDirectory().Path,
                        new[] { _configOptions.ConfigFilePath.Directory },
                        false,
                        _configOptions.ConfigFilePath.FileName.FullPath,
                        path =>
                    {
                        FilePath filePath = new FilePath(path);
                        if (_configOptions.ConfigFilePath.Equals(filePath))
                        {
                            _newEngine.Set();
                            _messageEvent.Set();
                        }
                    });
                }
            }

            // Start the message pump if an async process is running
            ExitCode exitCode = ExitCode.Normal;

            if (messagePump)
            {
                // 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(() =>
                    {
                        Trace.Information("Hit Ctrl-C to exit");
                        Console.TreatControlCAsInput = true;
                        while (true)
                        {
                            // Would have prefered 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;
                    }

                    // See if we need a new engine
                    if (_newEngine)
                    {
                        // Get a new engine
                        Trace.Information("Configuration file {0} has changed, re-running", _configOptions.ConfigFilePath);
                        engineManager.Dispose();
                        engineManager = EngineManager.Get(preprocessor, _configOptions);

                        // Configure and execute
                        if (!engineManager.Configure())
                        {
                            exitCode = ExitCode.ConfigurationError;
                            break;
                        }

                        TraceEnviornment(engineManager);

                        if (!engineManager.Execute())
                        {
                            exitCode = ExitCode.ExecutionError;
                        }

                        // Clear the changed files since we just re-ran
                        string changedFile;
                        while (_changedFiles.TryDequeue(out changedFile))
                        {
                        }

                        _newEngine.Unset();
                    }
                    else
                    {
                        // Execute if files have changed
                        HashSet <string> changedFiles = new HashSet <string>();
                        string           changedFile;
                        while (_changedFiles.TryDequeue(out changedFile))
                        {
                            if (changedFiles.Add(changedFile))
                            {
                                Trace.Verbose("{0} has changed", changedFile);
                            }
                        }
                        if (changedFiles.Count > 0)
                        {
                            Trace.Information("{0} files have changed, re-executing", changedFiles.Count);
                            if (!engineManager.Execute())
                            {
                                exitCode = ExitCode.ExecutionError;
                            }
                            previewServer?.TriggerReload();
                        }
                    }

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

                // Shutdown
                Trace.Information("Shutting down");
                engineManager.Dispose();
                inputFolderWatcher?.Dispose();
                configFileWatcher?.Dispose();
                previewServer?.Dispose();
            }

            return(exitCode);
        }
Ejemplo n.º 2
0
        protected override ExitCode RunCommand(Preprocessor preprocessor)
        {
            // Get the standard input stream
            _configOptions.Stdin = StandardInputReader.Read();

            // Fix the root folder and other files
            DirectoryPath currentDirectory = Environment.CurrentDirectory;

            _configOptions.RootPath       = _configOptions.RootPath == null ? currentDirectory : currentDirectory.Combine(_configOptions.RootPath);
            _logFilePath                  = _logFilePath == null ? null : _configOptions.RootPath.CombineFile(_logFilePath);
            _configOptions.ConfigFilePath = _configOptions.RootPath.CombineFile(_configOptions.ConfigFilePath ?? "config.wyam");

            // Set up the log file
            if (_logFilePath != null)
            {
                Trace.AddListener(new SimpleFileTraceListener(_logFilePath.FullPath));
            }

            // Get the engine and configurator
            EngineManager engineManager = EngineManager.Get(preprocessor, _configOptions);

            if (engineManager == null)
            {
                return(ExitCode.CommandLineError);
            }

            // Configure and execute
            if (!engineManager.Configure())
            {
                return(ExitCode.ConfigurationError);
            }

            if (_verifyConfig)
            {
                Trace.Information("No errors. Exiting.");
                return(ExitCode.Normal);
            }

            Trace.Information($"Root path:{Environment.NewLine}    {engineManager.Engine.FileSystem.RootPath}");
            Trace.Information($"Input path(s):{Environment.NewLine}    {string.Join(Environment.NewLine + "    ", engineManager.Engine.FileSystem.InputPaths)}");
            Trace.Information($"Output path:{Environment.NewLine}    {engineManager.Engine.FileSystem.OutputPath}");
            Trace.Information($"Settings:{Environment.NewLine}    {string.Join(Environment.NewLine + "    ", engineManager.Engine.Settings.Select(x => $"{x.Key}: {x.Value?.ToString() ?? "null"}"))}");
            if (!engineManager.Execute())
            {
                return(ExitCode.ExecutionError);
            }

            bool messagePump = false;

            // Start the preview server
            Server previewServer = null;

            if (_preview)
            {
                messagePump = true;
                DirectoryPath previewPath = _previewRoot == null
                    ? engineManager.Engine.FileSystem.GetOutputDirectory().Path
                    : engineManager.Engine.FileSystem.GetOutputDirectory(_previewRoot).Path;

                previewServer = PreviewServer.Start(previewPath, _previewPort, _previewForceExtension, _previewVirtualDirectory, _watch && !_noReload);
            }

            // Start the watchers
            IDisposable inputFolderWatcher = null;
            IDisposable configFileWatcher  = null;

            if (_watch)
            {
                messagePump = true;

                Trace.Information("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();
                });

                if (_configOptions.ConfigFilePath != null)
                {
                    Trace.Information("Watching configuration file {0}", _configOptions.ConfigFilePath);
                    configFileWatcher = new ActionFileSystemWatcher(
                        engineManager.Engine.FileSystem.GetOutputDirectory().Path,
                        new[] { _configOptions.ConfigFilePath.Directory },
                        false,
                        _configOptions.ConfigFilePath.FileName.FullPath,
                        path =>
                    {
                        FilePath filePath = new FilePath(path);
                        if (_configOptions.ConfigFilePath.Equals(filePath))
                        {
                            _newEngine.Set();
                            _messageEvent.Set();
                        }
                    });
                }
            }

            // Start the message pump if an async process is running
            ExitCode exitCode = ExitCode.Normal;

            if (messagePump)
            {
                // 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(() =>
                    {
                        Trace.Information("Hit any key to exit");
                        Console.ReadKey();
                        _exit.Set();
                        _messageEvent.Set();
                    })
                    {
                        IsBackground = true
                    };
                    thread.Start();
                }

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

                    // See if we need a new engine
                    if (_newEngine)
                    {
                        // Get a new engine
                        Trace.Information("Configuration file {0} has changed, re-running", _configOptions.ConfigFilePath);
                        engineManager.Dispose();
                        engineManager = EngineManager.Get(preprocessor, _configOptions);

                        // Configure and execute
                        if (!engineManager.Configure())
                        {
                            exitCode = ExitCode.ConfigurationError;
                            break;
                        }
                        Console.WriteLine($"Root path:{Environment.NewLine}  {engineManager.Engine.FileSystem.RootPath}");
                        Console.WriteLine($"Input path(s):{Environment.NewLine}  {string.Join(Environment.NewLine + "  ", engineManager.Engine.FileSystem.InputPaths)}");
                        Console.WriteLine($"Root path:{Environment.NewLine}  {engineManager.Engine.FileSystem.OutputPath}");
                        if (!engineManager.Execute())
                        {
                            exitCode = ExitCode.ExecutionError;
                        }

                        // Clear the changed files since we just re-ran
                        string changedFile;
                        while (_changedFiles.TryDequeue(out changedFile))
                        {
                        }

                        _newEngine.Unset();
                    }
                    else
                    {
                        // Execute if files have changed
                        HashSet <string> changedFiles = new HashSet <string>();
                        string           changedFile;
                        while (_changedFiles.TryDequeue(out changedFile))
                        {
                            if (changedFiles.Add(changedFile))
                            {
                                Trace.Verbose("{0} has changed", changedFile);
                            }
                        }
                        if (changedFiles.Count > 0)
                        {
                            Trace.Information("{0} files have changed, re-executing", changedFiles.Count);
                            if (!engineManager.Execute())
                            {
                                exitCode = ExitCode.ExecutionError;
                            }
                            previewServer?.TriggerReload();
                        }
                    }

                    // Check one more time for exit
                    if (_exit)
                    {
                        break;
                    }
                    Trace.Information("Hit any key to exit");
                    _messageEvent.Reset();
                }

                // Shutdown
                Trace.Information("Shutting down");
                engineManager.Dispose();
                inputFolderWatcher?.Dispose();
                configFileWatcher?.Dispose();
                previewServer?.Dispose();
            }

            return(exitCode);
        }