コード例 #1
0
        /// <inheritdoc />
        protected override int ExecuteCommand(CommandLineApplication app, IConsole console)
        {
            var appName = app.GetRootCommandLineApplication().Name;

            string executableDir = Path.GetDirectoryName(RunningAssembly.Info.Location);

            if (string.IsNullOrEmpty(executableDir))
            {
                throw new CommandException($"Could not find the directory of the executing assembly: {RunningAssembly.Info.Location}.");
            }

            var starterFilePath = GetStartScriptFilePath(appName);

            Log.Debug($"Creating starter script: {starterFilePath.PrettyQuote()}.");

            if (StaticUtilities.IsRuntimeWindowsPlatform)
            {
                File.WriteAllText(starterFilePath, $"@echo off\r\ndotnet exec \"%~dp0{GetDllName()}\" %*");
            }
            else
            {
                File.WriteAllText(starterFilePath, (@"#!/bin/bash
SOURCE=""${BASH_SOURCE[0]}""
while [ -h ""$SOURCE"" ]; do
    DIR=""$( cd -P ""$( dirname ""$SOURCE"" )"" && pwd )""
    SOURCE=""$(readlink ""$SOURCE"")""
    [[ $SOURCE != /* ]] && SOURCE=""$DIR/$SOURCE""
done
DIR=""$( cd -P ""$( dirname ""$SOURCE"" )"" && pwd )""
dotnet exec ""$DIR/" + GetDllName() + @""" ""$@""").Replace("\r", ""));
            }

            Log?.Info($"Starter script created: {starterFilePath.PrettyQuote()}.");

            HelpWriter.WriteOnNewLine(null);
            HelpWriter.WriteSectionTitle("IMPORTANT README:");
            HelpWriter.WriteOnNewLine(@"
A starter script has been created in the same directory as this executable: " + starterFilePath.PrettyQuote() + $@".

It allows you to call this tool in a more natural way: `{appName} [command]`. This strips the need to run the .dll with dotnet (the script does that for you).

The directory containing the starter script created should be added to your system PATH in order to be able to call `{appName} [command]` from anywhere on your system.

The command to add this directory to your path is:");
            HelpWriter.WriteOnNewLine(null);

            if (StaticUtilities.IsRuntimeWindowsPlatform)
            {
                Out.WriteResultOnNewLine($"for /f \"usebackq tokens=2,*\" %A in (`reg query HKCU\\Environment /v PATH`) do SetX Path \"%B;{Path.GetDirectoryName(starterFilePath)}\"");
            }
            else
            {
                Out.WriteResultOnNewLine($"echo \"export PATH=$PATH:{Path.GetDirectoryName(starterFilePath)}\" >> ~/.bashrc && source ~/.bashrc && chmod +x \"{starterFilePath}\"");
            }

            HelpWriter.WriteOnNewLine(null);

            return(0);
        }
コード例 #2
0
        protected override int ExecuteCommand(CommandLineApplication app, IConsole console)
        {
            if (string.IsNullOrEmpty(SourceDirectory))
            {
                SourceDirectory = Directory.GetCurrentDirectory();
                Log.Trace?.Write($"Using current directory to initialize the project: {SourceDirectory.PrettyQuote()}.");
            }

            SourceDirectory = SourceDirectory.ToAbsolutePath().ToCleanPath();

            if (string.IsNullOrEmpty(ProjectName))
            {
                ProjectName = Path.GetFileName(SourceDirectory);
                Log.Info($"Using directory name for the project name: {ProjectName.PrettyQuote()}.");
            }

            var projectDirectory = IsLocalProject ? OeBuilderConstants.GetProjectDirectoryLocal(SourceDirectory) : OeBuilderConstants.GetProjectDirectory(SourceDirectory);

            if (Utils.CreateDirectoryIfNeeded(projectDirectory, FileAttributes.Hidden))
            {
                Log.Info($"Created project directory: {projectDirectory.PrettyQuote()}.");
            }

            Log.Trace?.Write("Generating a default project.");
            var project = OeProject.GetStandardProject();

            var projectFilePath = Path.Combine(projectDirectory, $"{ProjectName}{OeBuilderConstants.OeProjectExtension}");

            if (File.Exists(projectFilePath))
            {
                if (Force)
                {
                    File.Delete(projectFilePath);
                }
                else
                {
                    throw new CommandValidationException($"The project file already exists, delete it first: {projectFilePath.PrettyQuote()}.");
                }
            }

            Log.Info($"Creating Openedge project file: {projectFilePath.PrettyQuote()}.");
            project.Save(projectFilePath);

            Log.Info($"Project created: {projectFilePath.PrettyQuote()}.");

            HelpWriter.WriteOnNewLine(null);
            HelpWriter.WriteSectionTitle("IMPORTANT README:");
            HelpWriter.WriteOnNewLine(@"
The project file created (" + OeBuilderConstants.OeProjectExtension + @") is defined in XML format and has a provided XML schema definition file (" + OeProject.XsdName + @").

The project XML schema is fully documented and should be used to enable intellisense in your favorite editor.
Example of xml editors with out-of-the-box intellisense (autocomplete) features for xml:

 - Progress Developer studio (eclipse)
 - Visual studio
 - Most jetbrain IDE

Drag and drop the created " + OeBuilderConstants.OeProjectExtension + @" file into the editor of your choice and start configuring your build.
The file " + Path.Combine(OeBuilderConstants.GetProjectDirectory(""), $"{ProjectName}{OeBuilderConstants.OeProjectExtension}").PrettyQuote() + @" should be versioned in your source repository to allow anyone who clones your application to build it.
The file " + OeProject.XsdName.PrettyQuote() + @", however, should not be versioned with your application because it depends on the version of this tool (sakoe). If this tool is updated, use the command " + typeof(ProjectUpdateCommand).GetFullCommandLine <MainCommand>().PrettyQuote() + @" to update the " + OeProject.XsdName.PrettyQuote() + @" to the latest version.

If you need to have a project file containing build configurations specific to your local machine, you can use the option " + (GetCommandOptionFromPropertyName(nameof(IsLocalProject))?.Template ?? "").PrettyQuote() + @". This will create the project file into the directory " + OeBuilderConstants.GetProjectDirectoryLocal("").PrettyQuote() + @" which should NOT be versioned.
For git repositories, use the command " + typeof(ProjectGitignoreCommand).GetFullCommandLine <MainCommand>().PrettyQuote() + @" to set up your .gitignore file for sakoe projects.");
            HelpWriter.WriteOnNewLine(null);
            return(0);
        }
コード例 #3
0
        /// <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);
        }