public static void GetAdditionalHelpText(IHelpWriter formatter, CommandLineApplication app, int firstColumnWidth) { formatter.WriteOnNewLine(null); formatter.WriteSectionTitle("OVERVIEW"); formatter.WriteOnNewLine(@"With sakoe, you can 'build' your project. A build process is a succession of tasks that (typically) transform your source files into a deliverable format, usually called a release or package. In sakoe, you describe a build process using a 'build configuration'. A build configuration holds 'properties' of the build (for instance, the path to the openedge installation directory $DLC). It also holds the list of 'tasks' that will be executed successively during the build process. To illustrate this, here is a possible build process: - Task 1: compile all your .p files to a `procedures` directory. - Task 2: compile all your .w files into a pro-library `client.pl`. - Task 3: zip the `procedures` and `client.pl` together into an archive file `release.zip`. In order to store these build configurations, sakoe uses project files: " + OeBuilderConstants.OeProjectExtension.PrettyQuote() + @". You can create them with the command: " + typeof(ProjectInitCommand).GetFullCommandLine <MainCommand>().PrettyQuote() + @"."); formatter.WriteOnNewLine(null); formatter.WriteOnNewLine(OeIncrementalBuildOptions.GetDefaultEnabledIncrementalBuild() ? "By default, a build is 'incremental'." : "A build can be 'incremental'."); formatter.WriteOnNewLine("An incremental build is the opposite of a full build. In incremental mode, only the files that were added/modified/deleted since the previous build are taken into account. Unchanged files are simply not rebuilt."); formatter.WriteOnNewLine(null); formatter.WriteOnNewLine("The chapters below contain more details about a project, build configuration, properties and tasks. "); // TODO: list all the node and their documentation, use a tree formatter.WriteOnNewLine(null); formatter.WriteSectionTitle("PROJECT"); formatter.WriteOnNewLine(BuilderHelp.GetPropertyDocumentation(typeof(OeProject).GetXmlName())); formatter.WriteOnNewLine(null); formatter.WriteSectionTitle("BUILD CONFIGURATION"); formatter.WriteOnNewLine(BuilderHelp.GetPropertyDocumentation(typeof(OeProject).GetXmlName(nameof(OeProject.BuildConfigurations)))); formatter.WriteOnNewLine(null); formatter.WriteSectionTitle("BUILD CONFIGURATION VARIABLES"); formatter.WriteOnNewLine(BuilderHelp.GetPropertyDocumentation(typeof(OeBuildConfiguration).GetXmlName(nameof(OeBuildConfiguration.Variables)))); formatter.WriteOnNewLine(null); formatter.WriteSectionTitle("BUILD CONFIGURATION PROPERTIES"); formatter.WriteOnNewLine(BuilderHelp.GetPropertyDocumentation(typeof(OeBuildConfiguration).GetXmlName(nameof(OeBuildConfiguration.Properties)))); formatter.WriteOnNewLine(null); formatter.WriteSectionTitle("BUILD STEPS"); formatter.WriteOnNewLine(BuilderHelp.GetPropertyDocumentation(typeof(OeBuildConfiguration).GetXmlName(nameof(OeBuildConfiguration.BuildSteps)))); formatter.WriteOnNewLine(null); }
/// <inheritdoc /> protected override int ExecuteCommand(CommandLineApplication app, IConsole console) { // TODO: show task error and compilation error // show help. if (ShowBuildPropertyHelp) { HelpWriter.WriteOnNewLine(null); HelpWriter.WriteSectionTitle("BUILD PROPERTIES"); foreach (var property in GetAvailableBuildProperties().OrderBy(p => p.Key)) { HelpWriter.WriteOnNewLine(property.Key); HelpWriter.WriteOnNewLine(BuilderHelp.GetPropertyDocumentation(property.Key), padding: 20); HelpWriter.WriteOnNewLine(null); } return(0); } if (string.IsNullOrEmpty(ProjectFile)) { ProjectFile = GetCurrentProjectFilePath(); } else { ProjectFile = GetProjectFilePath(ProjectFile); } Log?.Debug($"Base project file: {ProjectFile.PrettyQuote()}."); // get extra config var configQueue = new Queue <Tuple <string, string> >(); configQueue.Enqueue(new Tuple <string, string>(ProjectFile, ConfigurationName)); if (ExtraConfigurations != null) { foreach (var extraConfig in ExtraConfigurations) { if (string.IsNullOrEmpty(extraConfig)) { throw new CommandValidationException("The extra configuration option can't be empty."); } string file; string name; var split = extraConfig.Split('='); if (split.Length == 1) { file = ProjectFile; name = split[0]; } else if (split.Length == 2) { file = split[0]; name = split[1]; } else { throw new CommandValidationException("There should be only one character '=' in the extra configuration."); } configQueue.Enqueue(new Tuple <string, string>(file, name)); Log?.Debug($"Added an extra configuration: {name.PrettyQuote()} in {file.PrettyQuote()}."); } } // check properties var availableBuildProperties = GetAvailableBuildProperties(); var keyValueProperties = new Dictionary <string, string>(); if (BuildProperties != null) { foreach (var buildProperty in BuildProperties) { var split = buildProperty.Split('='); if (split.Length != 2) { throw new CommandValidationException($"There should be exactly one character '=' in the property {buildProperty.PrettyQuote()}."); } if (!availableBuildProperties.ContainsKey(split[0])) { throw new CommandValidationException($"The property {split[0].PrettyQuote()} does not exist, use the option {PropertyHelpLongName} to list the available properties."); } if (!keyValueProperties.ContainsKey(split[0])) { keyValueProperties.Add(split[0], split[1]); } else { Log?.Debug($"The property {split[0]} has been defined several times, we keep only the latest."); keyValueProperties[split[0]] = split[1]; } } } // check variables List <OeVariable> addedVariables = null; if (BuildVariables != null) { addedVariables = new List <OeVariable>(); foreach (var kpv in BuildVariables) { var split = kpv.Split('='); if (split.Length != 2) { throw new CommandValidationException($"There should be exactly one character '=' in the variable definition {kpv.PrettyQuote()}."); } addedVariables.Add(new OeVariable { Name = split[0], Value = split[1] }); } } var config = OeProject.GetConfiguration(configQueue); using (var builder = new BuilderAuto(config)) { builder.BuildConfiguration.Properties.SetPropertiesFromKeyValuePairs(keyValueProperties); if (addedVariables != null) { builder.BuildConfiguration.Variables.AddRange(addedVariables); } builder.BuildConfiguration.Properties.DlcDirectoryPath = GetDlcPath(); builder.CancelToken = CancelToken; builder.Log = GetLogger(); builder.Build(); // display compilation error. var compilationProblems = builder.CompilationProblems; if (compilationProblems.Count > 0) { Out.WriteErrorOnNewLine(null); Out.WriteErrorOnNewLine("COMPILATION ERRORS", ConsoleColor.Yellow, 1); var groups = compilationProblems.GroupBy(cp => cp.FilePath).ToList(); var i = 0; foreach (var filePathGrouped in groups) { Out.WriteErrorOnNewLine($"{(groups.Count - 1 == i ? "└─ " : "├─ ")}In {filePathGrouped.Key}:", indentation: 1); var j = 0; foreach (var problem in filePathGrouped) { Out.WriteErrorOnNewLine($"{(groups.Count - 1 == i ? " " : "│ ")}{(filePathGrouped.Count() - 1 == j ? "└─ " : "├─ ")}", indentation: 1); Out.WriteError($"Line {problem.Line}, Column {problem.Column}, error {problem.ErrorNumber} : {(string.IsNullOrEmpty(problem.FilePath) ? problem.Message : problem.Message.Replace(problem.FilePath, Path.GetFileName(problem.FilePath)))}", problem is OeCompilationWarning ? ConsoleColor.Yellow : ConsoleColor.Red, 1); j++; } i++; } } // display exceptions. var taskExceptions = builder.TaskExecutionExceptions; if (taskExceptions.Count > 0) { Out.WriteErrorOnNewLine(null); Out.WriteErrorOnNewLine("TASK EXCEPTIONS", ConsoleColor.Yellow, 1); var i = 0; foreach (var exception in taskExceptions) { Out.WriteErrorOnNewLine(taskExceptions.Count - 1 == i ? "└─ " : "├─ ", indentation: 1); Out.WriteError(exception.Message, exception.IsWarning ? ConsoleColor.Yellow : ConsoleColor.Red, 3); i++; } } } return(0); }