コード例 #1
0
ファイル: ProExecution.cs プロジェクト: devjerome/3P
        /// <summary>
        /// Creates a list of files to deploy after a compilation,
        /// for each Origin file will correspond one (or more if it's a .cls) .r file,
        /// and one .lst if the option has been checked
        /// </summary>
        public List <FileToDeploy> CreateListOfFilesToDeploy()
        {
            var outputList  = new List <FileToDeploy>();
            var clsNotFound = new StringBuilder();

            foreach (var treatedFile in ListToCompile)
            {
                // Is the input file a class file?
                if (treatedFile.InputPath.EndsWith(".cls", StringComparison.CurrentCultureIgnoreCase))
                {
                    // if the file we compiled inherits from another class or if another class inherits of our file,
                    // there is more than 1 *.r file generated. Moreover, they are generated in their package folders
                    try {
                        // for each *.r file
                        foreach (var file in Directory.EnumerateFiles(treatedFile.CompOutputDir, "*.r", SearchOption.AllDirectories))
                        {
                            var relativePath = file.Replace(treatedFile.CompOutputDir, "").TrimStart('\\');
                            var sourcePath   = ProEnv.FindFirstFileInPropath(Path.ChangeExtension(relativePath, ".cls"));

                            if (string.IsNullOrEmpty(sourcePath))
                            {
                                clsNotFound.Append("<div>" + relativePath + "</div>");
                            }
                            else
                            {
                                foreach (var deployNeeded in ProEnv.Deployer.GetTargetDirsNeededForFile(sourcePath, 0))
                                {
                                    string outputRPath;

                                    if (ProEnv.CompileLocally)
                                    {
                                        // deploy the *.r file next to his source
                                        outputRPath = Path.Combine(deployNeeded.TargetDir, Path.GetFileName(file));
                                    }
                                    else
                                    {
                                        // deploy the *.r file in the compilation directory (create the needed subdirectories...)
                                        outputRPath = Path.Combine(deployNeeded.TargetDir, relativePath);
                                    }

                                    // add .r and .lst (if needed) to the list of files to move
                                    outputList.Add(deployNeeded.Set(treatedFile.InputPath, file, outputRPath));

                                    if (ProEnv.CompileWithListing && Path.GetFileNameWithoutExtension(relativePath).Equals(Path.GetFileNameWithoutExtension(treatedFile.InputPath)))
                                    {
                                        outputList.Add(deployNeeded.Copy(treatedFile.InputPath, treatedFile.CompOutputLst, Path.ChangeExtension(outputRPath, ".lst")));
                                    }
                                }
                            }
                        }
                    } catch (Exception e) {
                        ErrorHandler.LogError(e);
                    }
                }
                else
                {
                    foreach (var deployNeeded in ProEnv.Deployer.GetTargetDirsNeededForFile(treatedFile.InputPath, 0))
                    {
                        // add .r and .lst (if needed) to the list of files to deploy
                        outputList.Add(deployNeeded.Set(treatedFile.InputPath, treatedFile.CompOutputR, Path.Combine(deployNeeded.TargetDir, treatedFile.BaseFileName + ".r")));

                        if (ProEnv.CompileWithListing)
                        {
                            outputList.Add(deployNeeded.Copy(treatedFile.InputPath, treatedFile.CompOutputLst, Path.Combine(deployNeeded.TargetDir, treatedFile.BaseFileName + ".lst")));
                        }
                    }
                }
            }

            if (clsNotFound.Length > 0)
            {
                UserCommunication.Notify("Couldn't locate the source file (.cls) for :" + clsNotFound + "in the propath", MessageImg.MsgError, "Post compilation error", "File not found");
            }

            return(outputList);
        }
コード例 #2
0
ファイル: ProExecution.cs プロジェクト: devjerome/3P
        /// <summary>
        /// allows to prepare the execution environnement by creating a unique temp folder
        /// and copying every critical files into it
        /// Then execute the progress program
        /// </summary>
        /// <returns></returns>
        public bool Do(ExecutionType executionType)
        {
            if (ListToCompile == null)
            {
                ListToCompile = new List <FileToCompile>();
            }

            ExecutionType = executionType;

            // check prowin32.exe
            if (!File.Exists(ProEnv.ProwinPath))
            {
                UserCommunication.NotifyUnique("ProExecutionChecks", "The file path to Prowin.exe is incorrect : <div class='ToolTipcodeSnippet'>" + ProEnv.ProwinPath + "</div>You must provide a valid path before executing this action<br><i>You can change this path in the <a href='go'>set environment page</a></i>", MessageImg.MsgWarning, "Execution error", "Invalid file path", args => {
                    Appli.Appli.GoToPage(PageNames.SetEnvironment);
                    UserCommunication.CloseUniqueNotif("ProExecutionChecks");
                    args.Handled = true;
                }, 10);
                return(false);
            }

            // check compilation dir
            if (executionType == ExecutionType.Compile && !ProEnv.CompileLocally && (!Path.IsPathRooted(ProEnv.BaseCompilationPath)))
            {
                UserCommunication.NotifyUnique("ProExecutionChecks", "The path for the compilation base directory is incorrect : <div class='ToolTipcodeSnippet'>" + (string.IsNullOrEmpty(ProEnv.BaseCompilationPath) ? "it's empty!" : ProEnv.BaseCompilationPath) + "</div>You must provide a valid path before executing this action :<br><br><i>1. Either change the compilation directory<br>2. Or toggle the option to compile next to the source file!<br><br>The options are configurable in the <a href='go'>set environment page</a></i>", MessageImg.MsgWarning, "Execution error", "Invalid file path", args => {
                    Appli.Appli.GoToPage(PageNames.SetEnvironment);
                    UserCommunication.CloseUniqueNotif("ProExecutionChecks");
                    args.Handled = true;
                }, 10);
                return(false);
            }

            // create a unique temporary folder
            LocalTempDir = Path.Combine(Config.FolderTemp, _proExecutionCounter + "-" + DateTime.Now.ToString("yyMMdd_HHmmssfff"));
            if (!Utils.CreateDirectory(LocalTempDir))
            {
                return(false);
            }

            // for each file of the list
            var           filesListPath    = Path.Combine(LocalTempDir, "files.list");
            StringBuilder filesListcontent = new StringBuilder();
            var           count            = 1;

            foreach (var fileToCompile in ListToCompile)
            {
                if (!File.Exists(fileToCompile.InputPath))
                {
                    UserCommunication.Notify("Couldn't find the following file :<br>" + fileToCompile.InputPath, MessageImg.MsgError, "Execution error", "File not found", 10);
                    return(false);
                }

                // if current file and the file has unsaved modif, we copy the content to a temp file, otherwise we just use the input path (also use the input path for .cls files!)
                if (fileToCompile.InputPath.Equals(Plug.CurrentFilePath) &&
                    (Npp.GetModify || (fileToCompile.BaseFileName ?? "").StartsWith("_")) &&
                    !Path.GetExtension(fileToCompile.InputPath).Equals(".cls"))
                {
                    fileToCompile.CompInputPath = Path.Combine(LocalTempDir, "tmp_" + DateTime.Now.ToString("yyMMdd_HHmmssfff_") + count + Path.GetExtension(fileToCompile.InputPath));
                    Utils.FileWriteAllText(fileToCompile.CompInputPath, Npp.Text, Encoding.Default);
                }
                else
                {
                    fileToCompile.CompInputPath = fileToCompile.InputPath;
                }

                if (executionType != ExecutionType.Compile)
                {
                    continue;
                }

                // we set where the *.lst and *.r files will be generated by the COMPILE command
                var baseFileName   = Path.GetFileNameWithoutExtension(fileToCompile.CompInputPath);
                var lastDeployment = ProEnv.Deployer.GetTargetDirsNeededForFile(fileToCompile.InputPath, 0).Last();

                // for *.cls files, as many *.r files are generated, we need to compile in a temp directory
                // we need to know which *.r files were generated for each input file
                // so each file gets his own sub tempDir
                if ((lastDeployment.DeployType != DeployType.Move) ||
                    Config.Instance.CompileForceUseOfTemp ||
                    Path.GetExtension(fileToCompile.InputPath).Equals(".cls")
                    )
                {
                    var subTempDir = Path.Combine(LocalTempDir, count.ToString());

                    // if the deployment dir is not on the same disk as the temp folder, we create a temp dir
                    // as close to the final deployment as possible (= in the deployment base dir!)
                    if (lastDeployment.DeployType != DeployType.Ftp && !string.IsNullOrEmpty(DistantRootTempDir) && DistantRootTempDir.Length > 2 && !DistantRootTempDir.Substring(0, 2).EqualsCi(LocalTempDir.Substring(0, 2)))
                    {
                        if (Utils.CreateDirectory(DistantRootTempDir, FileAttributes.Hidden))
                        {
                            DistantTempDir = Path.Combine(DistantRootTempDir, _proExecutionCounter + "-" + DateTime.Now.ToString("yyMMdd_HHmmssfff"));
                        }
                        else
                        {
                            DistantTempDir = LocalTempDir;
                        }

                        subTempDir = Path.Combine(DistantTempDir, count.ToString());
                    }

                    if (!Utils.CreateDirectory(subTempDir))
                    {
                        return(false);
                    }

                    fileToCompile.CompOutputDir = subTempDir;
                    fileToCompile.CompOutputLst = Path.Combine(subTempDir, baseFileName + ".lst");
                    fileToCompile.CompOutputR   = Path.Combine(subTempDir, baseFileName + ".r");
                }
                else
                {
                    // if we want to move the r-code somewhere during the deployment, then we will compile the r-code
                    // directly there, because it's faster than generating it in a temp folder and moving it afterward
                    fileToCompile.CompOutputDir = lastDeployment.TargetDir;
                    if (!Utils.CreateDirectory(fileToCompile.CompOutputDir))
                    {
                        return(false);
                    }

                    fileToCompile.CompOutputLst = Path.Combine(fileToCompile.CompOutputDir, baseFileName + ".lst");
                    fileToCompile.CompOutputR   = Path.Combine(fileToCompile.CompOutputDir, baseFileName + ".r");
                }

                // feed files list
                filesListcontent.AppendLine(fileToCompile.CompInputPath.ProQuoter() + " " + fileToCompile.CompOutputDir.ProQuoter() + " " + fileToCompile.CompOutputLst.ProQuoter());

                count++;
            }
            Utils.FileWriteAllText(filesListPath, filesListcontent.ToString(), Encoding.Default);

            // when running a procedure, check that a .r is not hiding the program, if that's the case we warn the user
            if (executionType == ExecutionType.Run && !_dontWarnAboutRCode && ListToCompile.Count >= 1)
            {
                if (File.Exists(Path.ChangeExtension(ListToCompile.First().InputPath, ".r")))
                {
                    UserCommunication.NotifyUnique("rcodehide", "Friendly warning, an <b>r-code</b> <i>(i.e. *.r file)</i> is hiding the current program<br>If you modified it since the last compilation you might not have the expected behavior...<br><br><i>" + "stop".ToHtmlLink("Click here to not show this message again for this session") + "</i>", MessageImg.MsgWarning, "Execution warning", "An Rcode hides the program", args => {
                        _dontWarnAboutRCode = true;
                        UserCommunication.CloseUniqueNotif("rcodehide");
                    }, 5);
                }
            }

            // Move ini file into the execution dir
            var baseIniPath = "";

            if (File.Exists(ProEnv.IniPath))
            {
                baseIniPath = Path.Combine(LocalTempDir, "base.ini");
                // we need to copy the .ini but we must delete the PROPATH= part, as stupid as it sounds, if we leave a huge PROPATH
                // in this file, it increases the compilation time by a stupid amount... unbelievable i know, but trust me, it does...
                var encoding    = TextEncodingDetect.GetFileEncoding(ProEnv.IniPath);
                var fileContent = Utils.ReadAllText(ProEnv.IniPath, encoding);
                var regex       = new Regex("^PROPATH=.*$", RegexOptions.Multiline | RegexOptions.IgnoreCase);
                var matches     = regex.Match(fileContent);
                if (matches.Success)
                {
                    fileContent = regex.Replace(fileContent, @"PROPATH=");
                }
                Utils.FileWriteAllText(baseIniPath, fileContent, encoding);
            }

            // Move pf file into the execution dir
            var basePfPath = "";

            if (File.Exists(ProEnv.GetPfPath()))
            {
                basePfPath = Path.Combine(LocalTempDir, "base.pf");
                File.Copy(ProEnv.GetPfPath(), basePfPath);
            }

            // set common info on the execution
            LogPath         = Path.Combine(LocalTempDir, "run.log");
            ProcessStartDir = executionType == ExecutionType.Run ? Path.GetDirectoryName(ListToCompile.First().InputPath) ?? LocalTempDir : LocalTempDir;
            ProgressWin32   = ProEnv.ProwinPath;
            if (executionType == ExecutionType.Database)
            {
                ExtractDbOutputPath = Path.Combine(LocalTempDir, ExtractDbOutputPath);
            }
            ProgressionFilePath    = Path.Combine(LocalTempDir, "compile.progression");
            DatabaseConnectionLog  = Path.Combine(LocalTempDir, "db.ko");
            NotificationOutputPath = Path.Combine(LocalTempDir, "postExecution.notif");
            var    propathToUse  = string.Join(",", ProEnv.GetProPathDirList);
            string fileToExecute = "";


            if (executionType == ExecutionType.Appbuilder)
            {
                fileToExecute = ListToCompile.First().InputPath;
            }
            else if (executionType == ExecutionType.Database)
            {
                // for database extraction, we need to copy the DumpDatabase program
                fileToExecute = "db_" + DateTime.Now.ToString("yyMMdd_HHmmssfff") + ".p";
                if (!Utils.FileWriteAllBytes(Path.Combine(LocalTempDir, fileToExecute), DataResources.DumpDatabase))
                {
                    return(false);
                }
            }
            else if (executionType == ExecutionType.Prolint)
            {
                // prolint, we need to copy the StartProlint program
                fileToExecute     = "prolint_" + DateTime.Now.ToString("yyMMdd_HHmmssfff") + ".p";
                ProlintOutputPath = Path.Combine(LocalTempDir, "prolint.log");
                StringBuilder prolintProgram = new StringBuilder();
                prolintProgram.AppendLine("&SCOPED-DEFINE PathFileToProlint " + ListToCompile.First().CompInputPath.ProQuoter());
                prolintProgram.AppendLine("&SCOPED-DEFINE PathProlintOutputFile " + ProlintOutputPath.ProQuoter());
                prolintProgram.AppendLine("&SCOPED-DEFINE PathToStartProlintProgram " + Config.FileStartProlint.ProQuoter());
                prolintProgram.AppendLine("&SCOPED-DEFINE UserName " + Config.Instance.UserName.ProQuoter());
                prolintProgram.AppendLine("&SCOPED-DEFINE PathActualFilePath " + ListToCompile.First().InputPath.ProQuoter());
                var filename = Path.GetFileName(Plug.CurrentFilePath);
                if (FileTag.Contains(filename))
                {
                    var fileInfo = FileTag.GetLastFileTag(filename);
                    prolintProgram.AppendLine("&SCOPED-DEFINE FileApplicationName " + fileInfo.ApplicationName.ProQuoter());
                    prolintProgram.AppendLine("&SCOPED-DEFINE FileApplicationVersion " + fileInfo.ApplicationVersion.ProQuoter());
                    prolintProgram.AppendLine("&SCOPED-DEFINE FileWorkPackage " + fileInfo.WorkPackage.ProQuoter());
                    prolintProgram.AppendLine("&SCOPED-DEFINE FileBugID " + fileInfo.BugId.ProQuoter());
                    prolintProgram.AppendLine("&SCOPED-DEFINE FileCorrectionNumber " + fileInfo.CorrectionNumber.ProQuoter());
                    prolintProgram.AppendLine("&SCOPED-DEFINE FileDate " + fileInfo.CorrectionDate.ProQuoter());
                }
                var encoding = TextEncodingDetect.GetFileEncoding(Config.FileStartProlint);
                Utils.FileWriteAllText(Path.Combine(LocalTempDir, fileToExecute), Utils.ReadAllText(Config.FileStartProlint, encoding).Replace(@"/*<inserted_3P_values>*/", prolintProgram.ToString()), encoding);
            }
            else if (executionType == ExecutionType.DeploymentHook)
            {
                fileToExecute = "hook_" + DateTime.Now.ToString("yyMMdd_HHmmssfff") + ".p";
                StringBuilder hookProc = new StringBuilder();
                hookProc.AppendLine("&SCOPED-DEFINE ApplicationName " + ProEnv.Name.ProQuoter());
                hookProc.AppendLine("&SCOPED-DEFINE ApplicationSuffix " + ProEnv.Suffix.ProQuoter());
                hookProc.AppendLine("&SCOPED-DEFINE StepNumber " + DeploymentStep);
                hookProc.AppendLine("&SCOPED-DEFINE SourceDirectory " + DeploymentSourcePath.ProQuoter());
                hookProc.AppendLine("&SCOPED-DEFINE DeploymentDirectory " + ProEnv.BaseCompilationPath.ProQuoter());
                var encoding = TextEncodingDetect.GetFileEncoding(Config.FileDeploymentHook);
                Utils.FileWriteAllText(Path.Combine(LocalTempDir, fileToExecute), Utils.ReadAllText(Config.FileDeploymentHook, encoding).Replace(@"/*<inserted_3P_values>*/", hookProc.ToString()), encoding);
            }
            else if (executionType == ExecutionType.DataDigger || executionType == ExecutionType.DataReader)
            {
                // need to init datadigger?
                if (!File.Exists(Path.Combine(Config.FolderDataDigger, "DataDigger.p")))
                {
                    if (!Utils.FileWriteAllBytes(Path.Combine(Config.FolderDataDigger, "DataDigger.zip"), DataResources.DataDigger))
                    {
                        return(false);
                    }
                    if (!Utils.ExtractAll(Path.Combine(Config.FolderDataDigger, "DataDigger.zip"), Config.FolderDataDigger))
                    {
                        return(false);
                    }
                }
                // add the datadigger folder to the propath
                propathToUse = Config.FolderDataDigger + "," + propathToUse;
            }
            else
            {
                if (ListToCompile.Count == 1)
                {
                    fileToExecute = ListToCompile.First().CompInputPath;
                }
            }

            // prepare the .p runner
            var           runnerPath    = Path.Combine(LocalTempDir, "run_" + DateTime.Now.ToString("yyMMdd_HHmmssfff") + ".p");
            StringBuilder runnerProgram = new StringBuilder();

            runnerProgram.AppendLine("&SCOPED-DEFINE ExecutionType " + executionType.ToString().ToUpper().ProQuoter());
            runnerProgram.AppendLine("&SCOPED-DEFINE ToExecute " + fileToExecute.ProQuoter());
            runnerProgram.AppendLine("&SCOPED-DEFINE LogFile " + LogPath.ProQuoter());
            runnerProgram.AppendLine("&SCOPED-DEFINE ExtractDbOutputPath " + ExtractDbOutputPath.ProQuoter());
            runnerProgram.AppendLine("&SCOPED-DEFINE propathToUse " + (LocalTempDir + "," + propathToUse).ProQuoter());
            runnerProgram.AppendLine("&SCOPED-DEFINE ExtraPf " + ProEnv.ExtraPf.Trim().ProQuoter());
            runnerProgram.AppendLine("&SCOPED-DEFINE BasePfPath " + basePfPath.Trim().ProQuoter());
            runnerProgram.AppendLine("&SCOPED-DEFINE CompileWithLst " + ProEnv.CompileWithListing);
            runnerProgram.AppendLine("&SCOPED-DEFINE ToCompileListFile " + filesListPath.ProQuoter());
            runnerProgram.AppendLine("&SCOPED-DEFINE CreateFileIfConnectFails " + DatabaseConnectionLog.ProQuoter());
            runnerProgram.AppendLine("&SCOPED-DEFINE CompileProgressionFile " + ProgressionFilePath.ProQuoter());
            runnerProgram.AppendLine("&SCOPED-DEFINE DbConnectionMandatory " + NeedDatabaseConnection);
            runnerProgram.AppendLine("&SCOPED-DEFINE NotificationOutputPath " + NotificationOutputPath.ProQuoter());
            runnerProgram.Append(Encoding.Default.GetString(DataResources.ProgressRun));
            Utils.FileWriteAllText(runnerPath, runnerProgram.ToString(), Encoding.Default);

            // preferably, we use the batch mode because it's faster than the client mode
            var batchMode = (executionType == ExecutionType.CheckSyntax || executionType == ExecutionType.Compile || executionType == ExecutionType.Database);

            // no batch mode option?
            batchMode = batchMode && !Config.Instance.NeverUseProwinInBatchMode;

            // multiple compilation, we don't want to show all those Prowin in the task bar...
            batchMode = batchMode && !NoBatch;

            // Parameters
            StringBuilder Params = new StringBuilder();

            if (executionType == ExecutionType.DataDigger || executionType == ExecutionType.DataReader)
            {
                Params.Append(" -s 10000 -d dmy -E -rereadnolock -h 255 -Bt 4000 -tmpbsize 8");
            }
            if (executionType != ExecutionType.Run)
            {
                Params.Append(" -T " + LocalTempDir.Trim('\\').ProQuoter());
            }
            if (!string.IsNullOrEmpty(baseIniPath))
            {
                Params.Append(" -ini " + baseIniPath.ProQuoter());
            }
            if (batchMode)
            {
                Params.Append(" -b");
            }
            Params.Append(" -p " + runnerPath.ProQuoter());
            if (!string.IsNullOrWhiteSpace(ProEnv.CmdLineParameters))
            {
                Params.Append(" " + ProEnv.CmdLineParameters.Trim());
            }
            ExeParameters = Params.ToString();

            // we supress the splashscreen
            if (!batchMode)
            {
                MoveSplashScreenNoError(Path.Combine(Path.GetDirectoryName(ProgressWin32) ?? "", "splashscreen.bmp"), Path.Combine(Path.GetDirectoryName(ProgressWin32) ?? "", "splashscreen-3p-disabled.bmp"));
            }

            // Start a process
            var pInfo = new ProcessStartInfo {
                FileName         = ProEnv.ProwinPath,
                Arguments        = ExeParameters,
                WorkingDirectory = ProcessStartDir
            };

            if (batchMode)
            {
                pInfo.WindowStyle    = ProcessWindowStyle.Hidden;
                pInfo.CreateNoWindow = true;
            }
            Process = new Process {
                StartInfo           = pInfo,
                EnableRaisingEvents = true
            };
            Process.Exited += ProcessOnExited;
            try {
                Process.Start();
            } catch (Exception e) {
                UserCommunication.NotifyUnique("ProwinFailed", "Couldn't start a new prowin process!<br>Please check that the file path to prowin32.exe is correct in the <a href='go'>set environment page</a>.<br><br>Below is the technical error that occured :<br><div class='ToolTipcodeSnippet'>" + e.Message + "</div>", MessageImg.MsgError, "Execution error", "Can't start a prowin process", args => {
                    Appli.Appli.GoToPage(PageNames.SetEnvironment);
                    UserCommunication.CloseUniqueNotif("ProwinFailed");
                    args.Handled = true;
                }, 10);
            }

            //UserCommunication.Notify("New process starting...<br><br><b>FileName :</b><br>" + ProEnv.ProwinPath + "<br><br><b>Parameters :</b><br>" + ExeParameters + "<br><br><b>Temporary directory :</b><br><a href='" + TempDir + "'>" + TempDir + "</a>");

            return(true);
        }