// Add all reference items to the assembly list private void AddReferencedAssemblies(PackageIdentity packageIdentify, DirectoryPath installedPath, PackageArchiveReader archiveReader) { List <FrameworkSpecificGroup> referenceItems = archiveReader.GetReferenceItems().ToList(); FrameworkSpecificGroup referenceGroup = GetMostCompatibleGroup(_currentFramework, referenceItems); if (referenceGroup != null) { Trace.Verbose($"Found compatible reference group {referenceGroup.TargetFramework.DotNetFrameworkName} for package {packageIdentify}"); foreach (FilePath itemPath in referenceGroup.Items .Select(x => new FilePath(x)) .Where(x => x.FileName.Extension == ".dll" || x.FileName.Extension == ".exe")) { FilePath assemblyPath = installedPath.CombineFile(itemPath); _assemblyLoader.Add(assemblyPath.FullPath); Trace.Verbose($"Added NuGet reference {assemblyPath} from package {packageIdentify} for loading"); } } else if (referenceItems.Count == 0) { // Only show a verbose message if there were no reference items (I.e., it's probably a content-only package or a metapackage and not a mismatch) Trace.Verbose($"Could not find any reference items in package {packageIdentify}"); } else { Trace.Verbose($"Could not find compatible reference group for package {packageIdentify} (found {string.Join(",", referenceItems.Select(x => x.TargetFramework.DotNetFrameworkName))})"); } }
private FilePath DefaultWritePath(IMetadata metadata, DirectoryPath prefix) { IDocument namespaceDocument = metadata.Get <IDocument>(CodeAnalysisKeys.ContainingNamespace); FilePath writePath = null; // Namespaces output to the index page in a folder of their full name if (metadata.String(CodeAnalysisKeys.Kind) == SymbolKind.Namespace.ToString()) { // If this namespace does not have a containing namespace, it's the global namespace writePath = new FilePath(namespaceDocument == null ? "global/index.html" : $"{metadata[CodeAnalysisKeys.DisplayName]}/index.html"); } // Types output to the index page in a folder of their SymbolId under the folder for their namespace else if (metadata.String(CodeAnalysisKeys.Kind) == SymbolKind.NamedType.ToString()) { // If containing namespace is null (shouldn't happen) or our namespace is global, output to root folder writePath = new FilePath(namespaceDocument?[CodeAnalysisKeys.ContainingNamespace] == null ? $"global/{metadata[CodeAnalysisKeys.SymbolId]}/index.html" : $"{namespaceDocument[CodeAnalysisKeys.DisplayName]}/{metadata[CodeAnalysisKeys.SymbolId]}/index.html"); } else { // Members output to a page equal to their SymbolId under the folder for their type IDocument containingTypeDocument = metadata.Get <IDocument>(CodeAnalysisKeys.ContainingType, null); writePath = new FilePath(containingTypeDocument?.FilePath(Keys.WritePath).FullPath.Replace("index.html", metadata.String(CodeAnalysisKeys.SymbolId) + ".html")); } // Add the prefix if (prefix != null) { writePath = prefix.CombineFile(writePath); } return(writePath); }
/// <inheritdoc /> public IEnumerable <IDocument> Execute(IReadOnlyList <IDocument> inputs, IExecutionContext context) { return(inputs.AsParallel().Select(context, input => { string fileName = _fileName.Invoke <string>(input, context); if (!string.IsNullOrWhiteSpace(fileName)) { fileName = GetFileName(fileName); if (!string.IsNullOrWhiteSpace(fileName)) { FilePath filePath = new FilePath(fileName); DirectoryPath relativeFileDir = input.DirectoryPath(Keys.RelativeFileDir); if (!string.IsNullOrWhiteSpace(_pathOutputKey) && relativeFileDir != null) { return context.GetDocument(input, new MetadataItems { { _outputKey, filePath }, { _pathOutputKey, relativeFileDir.CombineFile(filePath) } }); } return context.GetDocument(input, new MetadataItems { { _outputKey, filePath } }); } } return input; })); }
public async Task <FileInfo> DownloadFileAsync(Uri fileUri, DirectoryPath directory, string fileName, bool overwriteExistingFile = false) { return(await DownloadFileAsync(fileUri, directory.CombineFile(fileName), overwriteExistingFile)); }
public FileInfo DownloadFile(Uri fileUri, DirectoryPath directory, string fileName, bool overwriteExistingFile = false) { return(DownloadFile(fileUri, directory.CombineFile(fileName), overwriteExistingFile)); }
public void ShouldCombinePaths(string first, string second, string expected) { // Given DirectoryPath path = new DirectoryPath(first); // When FilePath result = path.CombineFile(new FilePath(second)); // Then Assert.AreEqual(expected, result.FullPath); }
public void CombiningWithRelativePathKeepsFirstProvider(string first, string second) { // Given DirectoryPath path = new DirectoryPath(new Uri("foo:///"), first); // When FilePath result = path.CombineFile(new FilePath(second)); // Then Assert.AreEqual(new Uri("foo:///"), result.FileProvider); }
protected IFile GetOutputFile(IDocument input, IExecutionContext context) { FilePath path = null; if (_useWriteMetadata) { string metadataKey = null; // WritePath path = input.FilePath(Keys.WritePath); if (path != null) { metadataKey = Keys.WritePath; } // WriteFileName DirectoryPath relativeFileDir = input.DirectoryPath(Keys.RelativeFileDir); FilePath writeFileName = input.FilePath(Keys.WriteFileName); if (path == null && relativeFileDir != null && writeFileName != null) { metadataKey = Keys.WriteFileName; path = relativeFileDir.CombineFile(writeFileName); } // WriteExtension FilePath relativeFilePath = input.FilePath(Keys.RelativeFilePath); string writeExtension = input.String(Keys.WriteExtension); if (path == null && relativeFilePath != null && !string.IsNullOrWhiteSpace(writeExtension)) { metadataKey = Keys.WriteExtension; path = relativeFilePath.ChangeExtension(writeExtension); } // Warn if needed if (metadataKey != null && _warnOnWriteMetadata) { Trace.Warning("An extension or delegate was specified for the WriteFiles module, but the metadata key {0} took precedence for the document with source {1}." + " Call UseWriteMetadata(false) to prevent the special write metadata keys from overriding WriteFiles constructor values.", metadataKey, input.SourceString()); } } // Func if (path == null) { path = _path.Invoke <FilePath>(input, context); } return(path != null?context.FileSystem.GetOutputFile(path) : null); }
public void CombiningWithAbsolutePathKeepsSecondProvider(string first, string second) { // Given DirectoryPath path = new DirectoryPath(new Uri("first:///"), first); // When FilePath result = path.CombineFile(new FilePath(new Uri("second:///"), second)); // Then Assert.AreEqual(new Uri("second:///"), result.FileProvider); }
public void ShouldThrowIfPathIsNull() { // Given DirectoryPath path = new DirectoryPath("assets"); // When TestDelegate test = () => path.CombineFile(null); // Then Assert.Throws <ArgumentNullException>(test); }
private static MainConfig ToMainConfig(this MainConfigModel model, DirectoryPath currentDirectory) { var myDatabase = new DatabaseConfig(new Uri(model.MyDatabase.Host), (int)uint.Parse(model.MyDatabase.Port), model.MyDatabase.Username, model.MyDatabase.Password, model.MyDatabase.DatabaseName); var log = new LogConfig(currentDirectory.CombineFile(model.Log.LogFilePath), model.Log.Level); return(new MainConfig(myDatabase, log)); }
private static void CreateBrowserRegistryKeys() { try { var homePath = new DirectoryPath(AppDomain.CurrentDomain.BaseDirectory); RegistryKey hkcu = Registry.CurrentUser; // Chrome var chromeKey = hkcu.CreateSubKey(ImportConst.RegistryChromeKey); chromeKey.SetValue("", homePath.CombineFile(ImportConst.ChromeManifestFilePath).FullPathWin); // Firefox var firefoxKey = hkcu.CreateSubKey(ImportConst.RegistryFirefoxKey); firefoxKey.SetValue("", homePath.CombineFile(ImportConst.FirefoxManifestFilePath).FullPathWin); hkcu.Close(); } catch (Exception ex) { LogTo.Error(ex, "Failed to create registry keys for browsers native messaging"); } }
public IFile GetFile(FilePath path) { if (path == null) { throw new ArgumentNullException(nameof(path)); } if (!path.IsRelative) { throw new ArgumentException("Path must be relative", nameof(path)); } return(new LocalFile(_path.CombineFile(path))); }
public void GetCommittersForInputDocument() { // Given DirectoryPath inputPath = new DirectoryPath(TestContext.CurrentContext.TestDirectory).Parent.Parent.Parent.Parent; IExecutionContext context = Substitute.For <IExecutionContext>(); context.FileSystem.RootPath.Returns(new DirectoryPath("/")); context.FileSystem.InputPaths.Returns(x => new[] { inputPath }); context.GetDocument(Arg.Any <IEnumerable <KeyValuePair <string, object> > >()).Returns(getNewDocumentCallInfo => { IDocument newDocument = Substitute.For <IDocument>(); newDocument.GetEnumerator() .Returns(getNewDocumentCallInfo.ArgAt <IEnumerable <KeyValuePair <string, object> > >(0).GetEnumerator()); newDocument.String(Arg.Any <string>()) .Returns(stringCallInfo => (string)getNewDocumentCallInfo.ArgAt <IEnumerable <KeyValuePair <string, object> > >(0).First(x => x.Key == stringCallInfo.ArgAt <string>(0)).Value); newDocument.Get <IReadOnlyDictionary <FilePath, string> >(Arg.Any <string>()) .Returns(getCallInfo => (IReadOnlyDictionary <FilePath, string>)getNewDocumentCallInfo.ArgAt <IEnumerable <KeyValuePair <string, object> > >(0).First(x => x.Key == getCallInfo.ArgAt <string>(0)).Value); newDocument.Get <IReadOnlyList <IDocument> >(Arg.Any <string>()) .Returns(getCallInfo => (IReadOnlyList <IDocument>)getNewDocumentCallInfo.ArgAt <IEnumerable <KeyValuePair <string, object> > >(0).First(x => x.Key == getCallInfo.ArgAt <string>(0)).Value); newDocument[Arg.Any <string>()] .Returns(getCallInfo => getNewDocumentCallInfo.ArgAt <IEnumerable <KeyValuePair <string, object> > >(0).First(x => x.Key == getCallInfo.ArgAt <string>(0)).Value); return(newDocument); }); IDocument document = Substitute.For <IDocument>(); document.Source.Returns(inputPath.CombineFile("Wyam.Core/IModule.cs")); // Use file that no longer exists so commit count is stable context.GetDocument(Arg.Any <IDocument>(), Arg.Any <IEnumerable <KeyValuePair <string, object> > >()).Returns(x => { IDocument newDocument = Substitute.For <IDocument>(); newDocument.GetEnumerator().Returns(x.ArgAt <IEnumerable <KeyValuePair <string, object> > >(1).GetEnumerator()); return(newDocument); }); GitContributors gitContributors = new GitContributors().ForEachInputDocument(); // When List <IDocument> results = gitContributors.Execute(new[] { document }, context).ToList(); // Make sure to materialize the result list // Then Assert.AreEqual(1, results.Count); List <IDocument> contributors = ((IEnumerable <IDocument>)results[0].First(x => x.Key == GitKeys.Contributors).Value).ToList(); Dictionary <string, object> contributor = contributors .Single(x => x.String(GitKeys.ContributorEmail) == "*****@*****.**" && x.String(GitKeys.ContributorName) == "Dave Glick") .ToDictionary(x => x.Key, x => x.Value); List <Dictionary <string, object> > commits = ((IEnumerable <IDocument>)contributor[GitKeys.Commits]) .Select(x => x.ToDictionary(y => y.Key, y => y.Value)).ToList(); Assert.That(commits.Count, Is.LessThan(10)); Assert.IsTrue(commits.All(x => (string)x[GitKeys.CommitterEmail] == "*****@*****.**" || (string)x[GitKeys.AuthorEmail] == "*****@*****.**")); }
/// <summary> /// Gets the output path of the input document. /// </summary> /// <param name="input">The input document.</param> /// <param name="context">The execution context.</param> /// <returns>The outout path.</returns> protected FilePath GetOutputPath(IDocument input, IExecutionContext context) { FilePath path = null; if (_useWriteMetadata) { string metadataKey = null; // WritePath path = input.FilePath(Keys.WritePath); if (path != null) { metadataKey = Keys.WritePath; } // WriteFileName DirectoryPath relativeFileDir = input.DirectoryPath(Keys.RelativeFileDir); FilePath writeFileName = input.FilePath(Keys.WriteFileName); if (path == null && relativeFileDir != null && writeFileName != null) { metadataKey = Keys.WriteFileName; path = relativeFileDir.CombineFile(writeFileName); } // WriteExtension FilePath relativeFilePath = input.FilePath(Keys.RelativeFilePath); string writeExtension = input.String(Keys.WriteExtension); if (path == null && relativeFilePath != null && !string.IsNullOrWhiteSpace(writeExtension)) { metadataKey = Keys.WriteExtension; path = relativeFilePath.ChangeExtension(writeExtension); } // Warn if needed if (metadataKey != null && _warnOnWriteMetadata) { Trace.Warning($"An extension or delegate was specified for the WriteFiles module, but the metadata key {metadataKey} took precedence for the document with source {input.SourceString()}" + $" resulting in an output path of {path}. Call UseWriteMetadata(false) to prevent the special write metadata keys from overriding WriteFiles constructor values."); } } // Fallback to the default behavior function return(path ?? _path.Invoke <FilePath>(input, context, "while getting path")); }
// Add all reference items to the assembly list private void AddReferencedAssemblies(DirectoryPath installedPath, PackageArchiveReader archiveReader) { FrameworkSpecificGroup referenceGroup = GetMostCompatibleGroup(_currentFramework, archiveReader.GetReferenceItems().ToList()); if (referenceGroup != null) { foreach (FilePath itemPath in referenceGroup.Items .Select(x => new FilePath(x)) .Where(x => x.FileName.Extension == ".dll" || x.FileName.Extension == ".exe")) { FilePath assemblyPath = installedPath.CombineFile(itemPath); _assemblyLoader.Add(assemblyPath.FullPath); Trace.Verbose($"Added NuGet reference {assemblyPath} for loading"); } } }
private string GetRelativePath(FilePath path, IExecutionContext context) { // Calculate a relative path from the input path(s) (or root) to the provided path if (path != null) { DirectoryPath inputPath = context.FileSystem.GetContainingInputPath(path) ?? new DirectoryPath("/"); if (path.IsRelative) { // If the path is relative, combine it with the input path to make it absolute path = inputPath.CombineFile(path); } return($"/{inputPath.GetRelativePath(path).FullPath}"); } // If there's no path, give this document a placeholder name return($"/{Path.GetRandomFileName()}.cshtml"); }
private Assembly AssemblyResolve(object sender, ResolveEventArgs e) { var assembly = AppDomain.CurrentDomain .GetAssemblies() .FirstOrDefault(a => a.FullName == e.Name); if (assembly != null) { return(assembly); } var assemblyName = e.Name.Split(',').First() + ".dll"; var homePath = new DirectoryPath(AppDomain.CurrentDomain.BaseDirectory); var assemblyPath = homePath.CombineFile(assemblyName); return(assemblyPath.Exists() == false ? null : Assembly.LoadFrom(assemblyPath.FullPath)); }
private FilePath DefaultWritePath(IMetadata metadata, DirectoryPath prefix) { IDocument namespaceDocument = metadata.Document(CodeAnalysisKeys.ContainingNamespace); FilePath writePath = null; // Assemblies output to the index page in a folder of their name if (metadata.String(CodeAnalysisKeys.Kind) == SymbolKind.Assembly.ToString()) { writePath = new FilePath($"{metadata[CodeAnalysisKeys.DisplayName]}/index.html"); } // Namespaces output to the index page in a folder of their full name else if (metadata.String(CodeAnalysisKeys.Kind) == SymbolKind.Namespace.ToString()) { // If this namespace does not have a containing namespace, it's the global namespace writePath = new FilePath(namespaceDocument == null ? "global/index.html" : $"{metadata[CodeAnalysisKeys.DisplayName]}/index.html"); } // Types output to the index page in a folder of their SymbolId under the folder for their namespace else if (metadata.String(CodeAnalysisKeys.Kind) == SymbolKind.NamedType.ToString()) { writePath = new FilePath(namespaceDocument?[CodeAnalysisKeys.ContainingNamespace] == null ? $"global/{metadata[CodeAnalysisKeys.SymbolId]}/index.html" : $"{namespaceDocument[CodeAnalysisKeys.DisplayName]}/{metadata[CodeAnalysisKeys.SymbolId]}/index.html"); } else { // Members output to a page equal to their SymbolId under the folder for their type IDocument containingTypeDocument = metadata.Document(CodeAnalysisKeys.ContainingType); string containingPath = containingTypeDocument.FilePath(Keys.WritePath).FullPath; if (prefix != null && containingPath.StartsWith(prefix.FullPath + "/")) { containingPath = containingPath.Substring(prefix.FullPath.Length + 1); } writePath = new FilePath(containingPath.Replace("index.html", metadata.String(CodeAnalysisKeys.SymbolId) + ".html")); } // Add the prefix if (prefix != null) { writePath = prefix.CombineFile(writePath); } return(writePath); }
public void GetCommitsForInputDocument() { // Given DirectoryPath inputPath = new DirectoryPath(TestContext.CurrentContext.TestDirectory).Parent.Parent.Parent.Parent; IExecutionContext context = Substitute.For <IExecutionContext>(); context.FileSystem.RootPath.Returns(new DirectoryPath("/")); context.FileSystem.InputPaths.Returns(x => new[] { inputPath }); context.GetDocument(Arg.Any <IEnumerable <KeyValuePair <string, object> > >()).Returns(getNewDocumentCallInfo => { IDocument newDocument = Substitute.For <IDocument>(); newDocument.GetEnumerator() .Returns(getNewDocumentCallInfo.ArgAt <IEnumerable <KeyValuePair <string, object> > >(0).GetEnumerator()); newDocument.Get <IReadOnlyDictionary <FilePath, string> >(Arg.Any <string>()) .Returns(getCallInfo => (IReadOnlyDictionary <FilePath, string>)getNewDocumentCallInfo.ArgAt <IEnumerable <KeyValuePair <string, object> > >(0).First(x => x.Key == getCallInfo.ArgAt <string>(0)).Value); return(newDocument); }); IDocument document = Substitute.For <IDocument>(); document.Source.Returns(inputPath.CombineFile("Wyam.Core/IModule.cs")); // Use file that no longer exists so commit count is stable context.GetDocument(Arg.Any <IDocument>(), Arg.Any <IEnumerable <KeyValuePair <string, object> > >()).Returns(x => { IDocument newDocument = Substitute.For <IDocument>(); newDocument.GetEnumerator().Returns(x.ArgAt <IEnumerable <KeyValuePair <string, object> > >(1).GetEnumerator()); return(newDocument); }); GitCommits gitCommits = new GitCommits().ForEachInputDocument(); // When List <IDocument> results = gitCommits.Execute(new[] { document }, context).ToList(); // Make sure to materialize the result list // Then Assert.AreEqual(1, results.Count); List <IDocument> commits = ((IEnumerable <IDocument>)results[0].First(x => x.Key == GitKeys.Commits).Value).ToList(); Assert.AreEqual(6, commits.Count); Assert.AreEqual("6274fb76a0380760ab2dc83f90748b7d953aceb4", commits.Last().First(x => x.Key == GitKeys.Sha).Value); }
private static bool CheckAndMoveNonEmptyFileSlots(int slotId, DirectoryPath recoverDirPath) { var wildCardPath = RegistryMemberBase.GetFilePathForSlotId(Core.SM.Collection, slotId, "*"); var fileNameWildCard = Path.GetFileName(wildCardPath); var dirPath = Path.GetDirectoryName(wildCardPath); fileNameWildCard.ThrowIfNullOrWhitespace("fileNameWildCard was null or whitespace"); dirPath.ThrowIfNullOrWhitespace("dirPath was null or whitespace"); recoverDirPath.EnsureExists(); bool moved = false; // TODO: Does there need to be a loop - only looking for one file? foreach (var filePath in Directory.EnumerateFiles(dirPath, fileNameWildCard, SearchOption.TopDirectoryOnly)) { try { // TODO: What if there is already a file in recover dir with the same name var date = DateTime.Today; var fileName = $"{date.Day}-{date.Month}-{date.Year}_{Path.GetFileName(filePath)}"; File.Move(filePath, recoverDirPath.CombineFile(fileName).FullPath); moved = true; } catch (IOException ex) { LogTo.Warning(ex, "Failed to move non-empty fileslot file {FilePath}", filePath); if (File.Exists(filePath)) { throw new InvalidOperationException($"Failed to remove non-empty fileslot file {filePath}"); } } } return(moved); }
public IFile GetFile(FilePath path) { return(_fileSystem.GetInputFile(_path.CombineFile(path))); }
public IFile GetFile(FilePath path) { return(new LocalFile(_path.CombineFile(path).Collapse())); }
protected virtual FilePath GetConfigFilePath(DirectoryPath dirPath, Type confType) { return(dirPath.CombineFile(confType.Name + ".json")); }
public PluginHost( string pluginPackageName, Guid sessionGuid, string smaChannelName, Process smaProcess, bool isDev) { // Connect to SMA var pluginMgr = RemotingServicesEx.ConnectToIpcServer <ISMAPluginManager>(smaChannelName); if (pluginMgr == null) { Exit(HostConst.ExitIpcConnectionError); return; } // Get required assemblies name IEnumerable <string> pluginAssemblies; IEnumerable <string> dependenciesAssemblies; if (isDev) { var homePath = new DirectoryPath(AppDomain.CurrentDomain.BaseDirectory); var pluginFilePath = homePath.CombineFile(pluginPackageName + ".dll"); pluginAssemblies = new List <string> { pluginFilePath.FullPath }; dependenciesAssemblies = new List <string>(); } else if (pluginMgr.GetAssembliesPathsForPlugin( sessionGuid, out pluginAssemblies, out dependenciesAssemblies) == false) { Exit(HostConst.ExitCouldNotGetAssembliesPaths); return; } // Setup assembly resolution AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolve; // Load & create plugin _plugin = LoadAssembliesAndCreatePluginInstance( dependenciesAssemblies, pluginAssemblies); if (_plugin == null) { Exit(HostConst.ExitNoPluginTypeFound); return; } // Connect plugin to SMA var sma = pluginMgr.ConnectPlugin( _plugin.ChannelName, sessionGuid); if (sma == null) { Exit(HostConst.ExitCouldNotConnectPlugin); return; } // Inject properties InjectPropertyDependencies(_plugin, sma, pluginMgr, sessionGuid, isDev); _plugin.OnInjected(); // Start monitoring SMA process if (StartMonitoringSMAProcess(smaProcess) == false) { Exit(HostConst.ExitParentExited); } }
private int Run(string[] args) { // Add a default trace listener Trace.AddListener(new SimpleColorConsoleTraceListener() { TraceOutputOptions = System.Diagnostics.TraceOptions.None }); // Output version info AssemblyInformationalVersionAttribute versionAttribute = Attribute.GetCustomAttribute(typeof(Program).Assembly, typeof(AssemblyInformationalVersionAttribute)) as AssemblyInformationalVersionAttribute; Trace.Information("Wyam version {0}", versionAttribute == null ? "unknown" : versionAttribute.InformationalVersion); // Parse the command line bool hasParseArgsErrors; if (!ParseArgs(args, out hasParseArgsErrors)) { return(hasParseArgsErrors ? (int)ExitCode.CommandLineError : (int)ExitCode.Normal); } // It's not a serious console app unless there's some ASCII art OutputLogo(); // Fix the root folder and other files DirectoryPath currentDirectory = Environment.CurrentDirectory; _rootPath = _rootPath == null ? currentDirectory : currentDirectory.Combine(_rootPath); _logFilePath = _logFilePath == null ? null : _rootPath.CombineFile(_logFilePath); _configFilePath = _rootPath.CombineFile(_configFilePath ?? "config.wyam"); // Set up the log file if (_logFilePath != null) { Trace.AddListener(new SimpleFileTraceListener(_logFilePath.FullPath)); } // Get the engine Engine engine = GetEngine(); if (engine == null) { return((int)ExitCode.CommandLineError); } // Populate engine's metadata if (!_verifyConfig && _globalRawMetadata != null && _globalRawMetadata.Count > 0) { try { engine.GlobalMetadata = new GlobalMetadataParser().Parse(_globalRawMetadata); } catch (MetadataParseException ex) { Trace.Error("Error while parsing metadata: {0}", ex.Message); if (Trace.Level == System.Diagnostics.SourceLevels.Verbose) { Trace.Error("Stack trace:{0}{1}", Environment.NewLine, ex.StackTrace); } return((int)ExitCode.CommandLineError); } // Not used anymore, release resources. _globalRawMetadata = null; } // Pause if (_pause) { Trace.Information("Pause requested, hit any key to continue"); Console.ReadKey(); } // Configure and execute if (!Configure(engine)) { return((int)ExitCode.ConfigurationError); } if (_verifyConfig) { Trace.Information("No errors. Exiting."); return((int)ExitCode.Normal); } Console.WriteLine($"Root path:{Environment.NewLine} {engine.FileSystem.RootPath}"); Console.WriteLine($"Input path(s):{Environment.NewLine} {string.Join(Environment.NewLine + " ", engine.FileSystem.InputPaths)}"); Console.WriteLine($"Output path:{Environment.NewLine} {engine.FileSystem.OutputPath}"); if (!Execute(engine)) { return((int)ExitCode.ExecutionError); } bool messagePump = false; // Start the preview server IDisposable previewServer = null; if (_preview) { messagePump = true; try { var rootPath = _previewRoot == null?engine.FileSystem.GetOutputDirectory().Path.FullPath : _previewRoot.FullPath; Trace.Information("Preview server listening on port {0} and serving from path {1}", _previewPort, rootPath); previewServer = Preview(engine, rootPath); } catch (Exception ex) { Trace.Critical("Error while running preview server: {0}", ex.Message); } } // Start the watchers IDisposable inputFolderWatcher = null; IDisposable configFileWatcher = null; if (_watch) { messagePump = true; Trace.Information("Watching paths(s) {0}", string.Join(", ", engine.FileSystem.InputPaths)); inputFolderWatcher = new ActionFileSystemWatcher(engine.FileSystem.GetOutputDirectory().Path, engine.FileSystem.GetInputDirectories().Select(x => x.Path), true, "*.*", path => { _changedFiles.Enqueue(path); _messageEvent.Set(); }); if (_configFilePath != null) { Trace.Information("Watching configuration file {0}", _configFilePath); Engine closureEngine = engine; configFileWatcher = new ActionFileSystemWatcher(engine.FileSystem.GetOutputDirectory().Path, new[] { _configFilePath.GetDirectory() }, false, _configFilePath.GetFilename().FullPath, path => { FilePath filePath = new FilePath(path); if (_configFilePath.Equals(filePath)) { _newEngine.Set(); _messageEvent.Set(); } }); } } // Start the message pump if an async process is running ExitCode exitCode = ExitCode.Normal; if (messagePump) { // Start the key listening thread Trace.Information("Hit any key to exit"); var thread = new Thread(() => { 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", _configFilePath); engine.Dispose(); engine = GetEngine(); // Configure and execute if (!Configure(engine)) { exitCode = ExitCode.ConfigurationError; break; } Console.WriteLine($"Root path:{Environment.NewLine} {engine.FileSystem.RootPath}"); Console.WriteLine($"Input path(s):{Environment.NewLine} {string.Join(Environment.NewLine + " ", engine.FileSystem.InputPaths)}"); Console.WriteLine($"Root path:{Environment.NewLine} {engine.FileSystem.OutputPath}"); if (!Execute(engine)) { exitCode = ExitCode.ExecutionError; break; } // 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 (!Execute(engine)) { exitCode = ExitCode.ExecutionError; break; } } } // Check one more time for exit if (_exit) { break; } Trace.Information("Hit any key to exit"); _messageEvent.Reset(); } // Shutdown Trace.Information("Shutting down"); engine.Dispose(); inputFolderWatcher?.Dispose(); configFileWatcher?.Dispose(); previewServer?.Dispose(); } return((int)exitCode); }