<commit_before>﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
#if !NETSTANDARD1_6
using System.Drawing;
#endif
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using FlubuCore.Commanding;
using FlubuCore.Context;
using FlubuCore.Infrastructure.Terminal;
using FlubuCore.IO;
using FlubuCore.Targeting;
using FlubuCore.Tasks.NetCore;
using FlubuCore.WebApi.Client;
using McMaster.Extensions.CommandLineUtils;
using Microsoft.DotNet.Cli.Utils;
using NuGet.Packaging;

namespace FlubuCore.Scripting
{
    public abstract class DefaultBuildScript : IBuildScript
    {
        private IFlubuSession _flubuSession;

        /// <summary>
        /// Get's product root directory.
        /// </summary>
        public FullPath RootDirectory => new FullPath(_flubuSession.Properties.GetProductRootDir());

        /// <summary>
        /// Get's output directory.
        /// </summary>
        public FullPath OutputDirectory => RootDirectory.CombineWith(new LocalPath(_flubuSession.Properties.GetOutputDir()));

        public int Run(IFlubuSession flubuSession)
        {
            _flubuSession = flubuSession;
            try
            {
                ConfigureDefaultProps(flubuSession);
                BeforeBuildExecution(flubuSession);
                RunBuild(flubuSession);
                flubuSession.Complete();
                AfterBuildExecution(flubuSession);
                return 0;
            }
            catch (TargetNotFoundException e)
            {
                flubuSession.ResetDepth();
                OnBuildFailed(flubuSession, e);
                AfterBuildExecution(flubuSession);
                if (flubuSession.Args.RethrowOnException)
                    throw;

                flubuSession.LogError(e.Message);
                return 3;
            }
            catch (WebApiException e)
            {
                flubuSession.ResetDepth();
                OnBuildFailed(flubuSession, e);
                AfterBuildExecution(flubuSession);
                if (flubuSession.Args.RethrowOnException)
                    throw;

                return 1;
            }
            catch (FlubuException e)
            {
                flubuSession.ResetDepth();
                OnBuildFailed(flubuSession, e);

                if (!flubuSession.Args.RethrowOnException)
                {
#if !NETSTANDARD1_6
                    flubuSession.LogError($"ERROR: {e.Message}", Color.Red);
#else
                    flubuSession.LogError($"error: {e.Message}");
#endif
                }

                AfterBuildExecution(flubuSession);
                if (flubuSession.Args.RethrowOnException)
                    throw;

                return 1;
            }
            catch (Exception e)
              {
                flubuSession.ResetDepth();
                OnBuildFailed(flubuSession, e);

                if (!flubuSession.Args.RethrowOnException)
                {
#if !NETSTANDARD1_6
                    flubuSession.LogError($"ERROR: {e}", Color.Red);
#else
                    flubuSession.LogError($"error: {e}");
#endif
                }

                AfterBuildExecution(flubuSession);
                if (flubuSession.Args.RethrowOnException)
                    throw;

                return 2;
            }
        }

        protected abstract void ConfigureBuildProperties(IBuildPropertiesContext context);

        protected abstract void ConfigureTargets(ITaskContext context);

        private static (List<string> targetsToRun, bool unknownTarget, List<string> notFoundTargets) ParseCmdLineArgs(
            List<string> mainCommands, TargetTree targetTree)
        {
            if (mainCommands == null || mainCommands.Count == 0) return (null, false, null);

            if (targetTree.HasAllTargets(mainCommands, out var notFoundTargets))
                return (mainCommands, false, null);

            return (new List<string> { "help" }, true, notFoundTargets);
        }

        private void RunBuild(IFlubuSession flubuSession)
        {
            bool resetTargetTree = false;

            ConfigureBuildProperties(flubuSession);

            ConfigureDefaultTargets(flubuSession);

            ScriptProperties.SetPropertiesFromScriptArg(this, flubuSession);

            TargetCreator.CreateTargetFromMethodAttributes(this, flubuSession);

            ConfigureTargets(flubuSession);

            var targetsInfo = default((List<string> targetsToRun, bool unknownTarget, List<string> notFoundTargets));

            if (!flubuSession.Args.InteractiveMode)
            {
                targetsInfo = ParseCmdLineArgs(flubuSession.Args.MainCommands, flubuSession.TargetTree);
                flubuSession.UnknownTarget = targetsInfo.unknownTarget;
                if (targetsInfo.targetsToRun == null || targetsInfo.targetsToRun.Count == 0)
                {
                    var defaultTargets = flubuSession.TargetTree.DefaultTargets;
                    targetsInfo.targetsToRun = new List<string>();
                    if (defaultTargets != null && defaultTargets.Count != 0)
                    {
                        foreach (var defaultTarget in defaultTargets)
                        {
                            targetsInfo.targetsToRun.Add(defaultTarget.TargetName);
                        }
                    }
                    else
                    {
                        targetsInfo.targetsToRun.Add("help");
                    }
                }

                ExecuteTarget(flubuSession, targetsInfo);
            }
            else
            {
                FlubuInteractiveMode(flubuSession, targetsInfo, resetTargetTree);
            }
        }

        private void ExecuteTarget(IFlubuSession flubuSession, (List<string> targetsToRun, bool unknownTarget, List<string> notFoundTargets) targetsInfo)
        {
            flubuSession.Start();

            //// specific target help
            if (targetsInfo.targetsToRun.Count == 2 &&
                targetsInfo.targetsToRun[1].Equals("help", StringComparison.OrdinalIgnoreCase))
            {
                flubuSession.TargetTree.RunTargetHelp(flubuSession, targetsInfo.targetsToRun[0]);
                return;
            }

            if (targetsInfo.targetsToRun.Count == 1 || !flubuSession.Args.ExecuteTargetsInParallel)
            {
                if (targetsInfo.targetsToRun[0].Equals("help", StringComparison.OrdinalIgnoreCase))
                {
                    flubuSession.TargetTree.ScriptArgsHelp = ScriptProperties.GetPropertiesHelp(this);
                }

                BeforeTargetExecution(flubuSession);
                foreach (var targetToRun in targetsInfo.targetsToRun)
                {
                    flubuSession.TargetTree.RunTarget(flubuSession, targetToRun);
                }

                AfterTargetExecution(flubuSession);
            }
            else
            {
                flubuSession.LogInfo("Running target's in parallel.");
                var tasks = new List<Task>();
                BeforeTargetExecution(flubuSession);
                foreach (var targetToRun in targetsInfo.targetsToRun)
                {
                    tasks.Add(flubuSession.TargetTree.RunTargetAsync(flubuSession, targetToRun, true));
                }

                Task.WaitAll(tasks.ToArray());
                AfterTargetExecution(flubuSession);
            }

            if (targetsInfo.unknownTarget)
            {
                var targetNotFoundMsg = $"Target {string.Join(" and ", targetsInfo.notFoundTargets)} not found.";
                if (flubuSession.Args.InteractiveMode)
                {
                    flubuSession.LogInfo(targetNotFoundMsg);
                }
                else
                {
                    throw new TargetNotFoundException(targetNotFoundMsg);
                }
            }

            AssertAllTargetDependenciesWereExecuted(flubuSession);
        }

        private void FlubuInteractiveMode(IFlubuSession flubuSession, (List<string> targetsToRun, bool unknownTarget, List<string> notFoundTargets) targetsInfo, bool resetTargetTree)
        {
            flubuSession.InteractiveMode = true;
            var flubuConsole = InitializeFlubuConsole(flubuSession);
            flubuSession.TargetTree.RunTarget(flubuSession, "help.onlyTargets");
            flubuSession.LogInfo(" ");

            do
            {
                if (flubuSession.InteractiveMode)
                {
                    var commandLine = flubuConsole.ReadLine(Directory.GetCurrentDirectory());

                    if (string.IsNullOrEmpty(commandLine))
                    {
                        continue;
                    }

                    var app = new CommandLineApplication(false);
                    IFlubuCommandParser parser = new FlubuCommandParser(app, null);
                    var args = parser.Parse(commandLine.Split(' ')
                        .Where(x => !string.IsNullOrWhiteSpace(x))
                        .Select(x => x.Trim()).ToArray());
                    targetsInfo = ParseCmdLineArgs(args.MainCommands, flubuSession.TargetTree);

                    flubuSession.InteractiveArgs = args;
                    flubuSession.ScriptArgs = args.ScriptArguments;
                    ScriptProperties.SetPropertiesFromScriptArg(this, flubuSession);

                    if (args.MainCommands.Count == 0)
                    {
                        continue;
                    }

                    if (CommandExecutor.InteractiveExitCommands.Contains(args.MainCommands[0], StringComparer.OrdinalIgnoreCase))
                    {
                        break;
                    }

                    if (targetsInfo.unknownTarget)
                    {
                        var internalCommandExecuted = flubuConsole.ExecuteInternalCommand(commandLine);
                        if (internalCommandExecuted)
                        {
                            continue;
                        }

                        var splitedLine = commandLine.Split(' ').ToList();
                        var command = splitedLine.First();
                        var runProgram = flubuSession.Tasks().RunProgramTask(command).DoNotLogTaskExecutionInfo().WorkingFolder(".");
                        splitedLine.RemoveAt(0);<commit_msg>build fix<commit_after>﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
#if !NETSTANDARD1_6
using System.Drawing;
#endif
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using FlubuCore.Commanding;
using FlubuCore.Context;
using FlubuCore.Infrastructure.Terminal;
using FlubuCore.IO;
using FlubuCore.Targeting;
using FlubuCore.Tasks.NetCore;
using FlubuCore.WebApi.Client;
using McMaster.Extensions.CommandLineUtils;
using Microsoft.DotNet.Cli.Utils;
using NuGet.Packaging;

namespace FlubuCore.Scripting
{
    public abstract class DefaultBuildScript : IBuildScript
    {
        private IFlubuSession _flubuSession;

        /// <summary>
        /// Get's product root directory.
        /// </summary>
        public FullPath RootDirectory => new FullPath(_flubuSession.Properties.GetProductRootDir());

        /// <summary>
        /// Get's output directory.
        /// </summary>
        public FullPath OutputDirectory => RootDirectory.CombineWith(new LocalPath(_flubuSession.Properties.GetOutputDir()));

        public int Run(IFlubuSession flubuSession)
        {
            _flubuSession = flubuSession;
            try
            {
                ConfigureDefaultProps(flubuSession);
                BeforeBuildExecution(flubuSession);
                RunBuild(flubuSession);
                flubuSession.Complete();
                AfterBuildExecution(flubuSession);
                return 0;
            }
            catch (TargetNotFoundException e)
            {
                flubuSession.ResetDepth();
                OnBuildFailed(flubuSession, e);
                AfterBuildExecution(flubuSession);
                if (flubuSession.Args.RethrowOnException)
                    throw;

                flubuSession.LogError(e.Message);
                return 3;
            }
            catch (WebApiException e)
            {
                flubuSession.ResetDepth();
                OnBuildFailed(flubuSession, e);
                AfterBuildExecution(flubuSession);
                if (flubuSession.Args.RethrowOnException)
                    throw;

                return 1;
            }
            catch (FlubuException e)
            {
                flubuSession.ResetDepth();
                OnBuildFailed(flubuSession, e);

                if (!flubuSession.Args.RethrowOnException)
                {
#if !NETSTANDARD1_6
                    flubuSession.LogError($"ERROR: {e.Message}", Color.Red);
#else
                    flubuSession.LogError($"error: {e.Message}");
#endif
                }

                AfterBuildExecution(flubuSession);
                if (flubuSession.Args.RethrowOnException)
                    throw;

                return 1;
            }
            catch (Exception e)
              {
                flubuSession.ResetDepth();
                OnBuildFailed(flubuSession, e);

                if (!flubuSession.Args.RethrowOnException)
                {
#if !NETSTANDARD1_6
                    flubuSession.LogError($"ERROR: {e}", Color.Red);
#else
                    flubuSession.LogError($"error: {e}");
#endif
                }

                AfterBuildExecution(flubuSession);
                if (flubuSession.Args.RethrowOnException)
                    throw;

                return 2;
            }
        }

        protected abstract void ConfigureBuildProperties(IBuildPropertiesContext context);

        protected abstract void ConfigureTargets(ITaskContext context);

        private static (List<string> targetsToRun, bool unknownTarget, List<string> notFoundTargets) ParseCmdLineArgs(
            List<string> mainCommands, TargetTree targetTree)
        {
            if (mainCommands == null || mainCommands.Count == 0) return (null, false, null);

            if (targetTree.HasAllTargets(mainCommands, out var notFoundTargets))
                return (mainCommands, false, null);

            return (new List<string> { "help" }, true, notFoundTargets);
        }

        private void RunBuild(IFlubuSession flubuSession)
        {
            bool resetTargetTree = false;

            ConfigureBuildProperties(flubuSession);

            ConfigureDefaultTargets(flubuSession);

            ScriptProperties.SetPropertiesFromScriptArg(this, flubuSession);

            TargetCreator.CreateTargetFromMethodAttributes(this, flubuSession);

            ConfigureTargets(flubuSession);

            var targetsInfo = default((List<string> targetsToRun, bool unknownTarget, List<string> notFoundTargets));

            if (!flubuSession.Args.InteractiveMode)
            {
                targetsInfo = ParseCmdLineArgs(flubuSession.Args.MainCommands, flubuSession.TargetTree);
                flubuSession.UnknownTarget = targetsInfo.unknownTarget;
                if (targetsInfo.targetsToRun == null || targetsInfo.targetsToRun.Count == 0)
                {
                    var defaultTargets = flubuSession.TargetTree.DefaultTargets;
                    targetsInfo.targetsToRun = new List<string>();
                    if (defaultTargets != null && defaultTargets.Count != 0)
                    {
                        foreach (var defaultTarget in defaultTargets)
                        {
                            targetsInfo.targetsToRun.Add(defaultTarget.TargetName);
                        }
                    }
                    else
                    {
                        targetsInfo.targetsToRun.Add("help");
                    }
                }

                ExecuteTarget(flubuSession, targetsInfo);
            }
            else
            {
                FlubuInteractiveMode(flubuSession, targetsInfo, resetTargetTree);
            }
        }

        private void ExecuteTarget(IFlubuSession flubuSession, (List<string> targetsToRun, bool unknownTarget, List<string> notFoundTargets) targetsInfo)
        {
            flubuSession.Start();

            //// specific target help
            if (targetsInfo.targetsToRun.Count == 2 &&
                targetsInfo.targetsToRun[1].Equals("help", StringComparison.OrdinalIgnoreCase))
            {
                flubuSession.TargetTree.RunTargetHelp(flubuSession, targetsInfo.targetsToRun[0]);
                return;
            }

            if (targetsInfo.targetsToRun.Count == 1 || !flubuSession.Args.ExecuteTargetsInParallel)
            {
                if (targetsInfo.targetsToRun[0].Equals("help", StringComparison.OrdinalIgnoreCase))
                {
                    flubuSession.TargetTree.ScriptArgsHelp = ScriptProperties.GetPropertiesHelp(this);
                }

                BeforeTargetExecution(flubuSession);
                foreach (var targetToRun in targetsInfo.targetsToRun)
                {
                    flubuSession.TargetTree.RunTarget(flubuSession, targetToRun);
                }

                AfterTargetExecution(flubuSession);
            }
            else
            {
                flubuSession.LogInfo("Running target's in parallel.");
                var tasks = new List<Task>();
                BeforeTargetExecution(flubuSession);
                foreach (var targetToRun in targetsInfo.targetsToRun)
                {
                    tasks.Add(flubuSession.TargetTree.RunTargetAsync(flubuSession, targetToRun, true));
                }

                Task.WaitAll(tasks.ToArray());
                AfterTargetExecution(flubuSession);
            }

            if (targetsInfo.unknownTarget)
            {
                var targetNotFoundMsg = $"Target {string.Join(" and ", targetsInfo.notFoundTargets)} not found.";
                if (flubuSession.Args.InteractiveMode)
                {
                    flubuSession.LogInfo(targetNotFoundMsg);
                }
                else
                {
                    throw new TargetNotFoundException(targetNotFoundMsg);
                }
            }

            AssertAllTargetDependenciesWereExecuted(flubuSession);
        }

        private void FlubuInteractiveMode(IFlubuSession flubuSession, (List<string> targetsToRun, bool unknownTarget, List<string> notFoundTargets) targetsInfo, bool resetTargetTree)
        {
            flubuSession.InteractiveMode = true;
            var flubuConsole = InitializeFlubuConsole(flubuSession);
            flubuSession.TargetTree.RunTarget(flubuSession, "help.onlyTargets");
            flubuSession.LogInfo(" ");

            do
            {
                if (flubuSession.InteractiveMode)
                {
                    var commandLine = flubuConsole.ReadLine(Directory.GetCurrentDirectory());

                    if (string.IsNullOrEmpty(commandLine))
                    {
                        continue;
                    }

                    var app = new CommandLineApplication(false);
                    IFlubuCommandParser parser = new FlubuCommandParser(app, null);
                    var args = parser.Parse(commandLine.Split(' ')
                        .Where(x => !string.IsNullOrWhiteSpace(x))
                        .Select(x => x.Trim()).ToArray());
                    targetsInfo = ParseCmdLineArgs(args.MainCommands, flubuSession.TargetTree);

                    flubuSession.InteractiveArgs = args;
                    flubuSession.ScriptArgs = args.ScriptArguments;
                    ScriptProperties.SetPropertiesFromScriptArg(this, flubuSession);

                    if (args.MainCommands.Count == 0)
                    {
                        continue;
                    }

                    if (CommandExecutor.InteractiveExitAndReloadCommands.Contains(args.MainCommands[0], StringComparer.OrdinalIgnoreCase))
                    {
                        break;
                    }

                    if (targetsInfo.unknownTarget)
                    {
                        var internalCommandExecuted = flubuConsole.ExecuteInternalCommand(commandLine);
                        if (internalCommandExecuted)
                        {
                            continue;
                        }

                        var splitedLine = commandLine.Split(' ').ToList();
                        var command = splitedLine.First();
                        var runProgram = flubuSession.Tasks().RunProgramTask(command).DoNotLogTaskExecutionInfo().WorkingFolder(".");
                        splitedLine.RemoveAt(0);
{'fraction_non_alphanumeric': 0.08039431497344117, 'fraction_numerical': 0.0021055653921615543, 'mean_word_length': 1.6155193992490613, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '361633', 'n_tokens_mistral': 5395, 'n_tokens_neox': 5006, 'n_words': 844}