From f250d1638b1902d84abb693d5b23cde8fd61ff5c Mon Sep 17 00:00:00 2001 From: Casper Hornstrup Date: Wed, 23 Nov 2005 17:25:55 +0000 Subject: [PATCH] ReactOS Sin Verifier svn path=/trunk/; revision=19490 --- cis/ReactOS.Verify/App.config | 9 + cis/ReactOS.Verify/AssemblyInfo.cs | 14 ++ cis/ReactOS.Verify/Default.build | 20 ++ cis/ReactOS.Verify/Main.cs | 279 ++++++++++++++++++++++ cis/ReactOS.Verify/RedirectableProcess.cs | 145 +++++++++++ 5 files changed, 467 insertions(+) create mode 100644 cis/ReactOS.Verify/App.config create mode 100644 cis/ReactOS.Verify/AssemblyInfo.cs create mode 100644 cis/ReactOS.Verify/Default.build create mode 100644 cis/ReactOS.Verify/Main.cs create mode 100644 cis/ReactOS.Verify/RedirectableProcess.cs diff --git a/cis/ReactOS.Verify/App.config b/cis/ReactOS.Verify/App.config new file mode 100644 index 00000000000..45b24c6e7fe --- /dev/null +++ b/cis/ReactOS.Verify/App.config @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/cis/ReactOS.Verify/AssemblyInfo.cs b/cis/ReactOS.Verify/AssemblyInfo.cs new file mode 100644 index 00000000000..f3000d00415 --- /dev/null +++ b/cis/ReactOS.Verify/AssemblyInfo.cs @@ -0,0 +1,14 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +[assembly: AssemblyTitle("ReactOS Sin Verifier")] +[assembly: AssemblyDescription("ReactOS Sin Verifier")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("ReactOS Project")] +[assembly: AssemblyProduct("React Operating System")] +[assembly: AssemblyCopyright("Copyright 2005 ReactOS Project")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyDelaySign(false)] +[assembly: AssemblyKeyFile("")] diff --git a/cis/ReactOS.Verify/Default.build b/cis/ReactOS.Verify/Default.build new file mode 100644 index 00000000000..da799e116ff --- /dev/null +++ b/cis/ReactOS.Verify/Default.build @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + diff --git a/cis/ReactOS.Verify/Main.cs b/cis/ReactOS.Verify/Main.cs new file mode 100644 index 00000000000..f997a8dbcc3 --- /dev/null +++ b/cis/ReactOS.Verify/Main.cs @@ -0,0 +1,279 @@ +using System; +using System.IO; +using System.Diagnostics; +using System.Configuration; +using System.Web.Mail; +using System.Collections; +using System.Collections.Specialized; + +namespace ReactOS.Verify +{ + public class MainClass + { + /// + /// Run the application. + /// + /// Script to run. + /// Arguments to pass to script. + /// Working directory. + /// Receives standard output. + /// Receives standard error. + /// + /// Exit code. + /// + private static int RunScript(string script, + string args, + string workingDirectory, + StringDictionary environmentVarables, + out string standardOutput, + out string standardError) + { + ProcessStartInfo scriptProcessStartInfo = new ProcessStartInfo(script, + args); + scriptProcessStartInfo.CreateNoWindow = true; + /* + * All standard streams must be redirected. + * Otherwise DuplicateHandle() will fail. + */ + scriptProcessStartInfo.RedirectStandardInput = true; + scriptProcessStartInfo.RedirectStandardError = true; + scriptProcessStartInfo.RedirectStandardOutput = true; + scriptProcessStartInfo.UseShellExecute = false; + scriptProcessStartInfo.WorkingDirectory = workingDirectory; + if (environmentVarables != null) + { + foreach (DictionaryEntry de in environmentVarables) + scriptProcessStartInfo.EnvironmentVariables.Add(de.Key as string, de.Value as string); + } + RedirectableProcess redirectableProcess = new RedirectableProcess(scriptProcessStartInfo); + standardOutput = redirectableProcess.ProcessOutput; + standardError = redirectableProcess.ProcessError; + return redirectableProcess.ExitCode; + } + + /// + /// Retrieve value of configuration from configuration file. + /// + /// Name of configuration option. + /// + /// Default value to be returned if the option does not exist. + /// + /// + /// Value of configuration option or null if the option does not + /// exist and no default value is provided. + /// + private static string GetConfigurationOption(string name, + string defaultValue) + { + if (ConfigurationSettings.AppSettings[name] != null) + { + string s = ConfigurationSettings.AppSettings[name].Trim(); + return s.Equals(String.Empty) ? defaultValue : s; + } + else + return defaultValue; + } + + /// + /// Send an email. + /// + /// Subject of the email. + /// Content of the email. + private static void SendErrorMail(string subject, string body) + { + try + { + string smtpServer = GetConfigurationOption("smtpServer", "localhost"); + string email = GetConfigurationOption("errorEmail", null); + if (email == null) + return; + MailMessage mm = new MailMessage(); + mm.Priority = MailPriority.Normal; + mm.From = email; + mm.To = email; + mm.Subject = subject; + mm.Body += body; + mm.Body += "
"; + mm.BodyFormat = MailFormat.Html; + SmtpMail.SmtpServer = smtpServer; + SmtpMail.Send(mm); + } + catch (Exception ex) + { + Console.Error.WriteLine(ex.Message); + } + } + + /// + /// Fail with an error message. + /// + /// Error message. + private static void Fail(string text) + { + Console.WriteLine(text); + } + + /// + /// Paths to fast disk for temporary files. + /// + private static string TemporaryFastDisk + { + get + { + string temporaryFastDisk = GetConfigurationOption("temporaryFastDisk", null); + if (temporaryFastDisk == null || temporaryFastDisk.Trim().Equals(String.Empty)) + return null; + return temporaryFastDisk.Trim(); + } + } + + /// + /// Paths to fast disk for intermediate files. + /// + private static string IntermediateFastDisk + { + get + { + string intermediateFastDisk = GetConfigurationOption("intermediateFastDisk", null); + if (intermediateFastDisk == null || intermediateFastDisk.Trim().Equals(String.Empty)) + return null; + return intermediateFastDisk.Trim(); + } + } + + /// + /// Paths to fast disk for output files. + /// + private static string OutputFastDisk + { + get + { + string outputFastDisk = GetConfigurationOption("outputFastDisk", null); + if (outputFastDisk == null || outputFastDisk.Trim().Equals(String.Empty)) + return null; + return outputFastDisk.Trim(); + } + } + + /// + /// Return collection of environment variables. + /// + /// Collection of environment variables or null if there is none. + private static StringDictionary GetEnvironmentVarables() + { + StringDictionary environmentVarables = new StringDictionary(); + if (TemporaryFastDisk != null) + environmentVarables.Add("ROS_TEMPORARY", TemporaryFastDisk); + if (IntermediateFastDisk != null) + environmentVarables.Add("ROS_INTERMEDIATE", IntermediateFastDisk); + if (OutputFastDisk != null) + environmentVarables.Add("ROS_OUTPUT", OutputFastDisk); + return environmentVarables; + } + + /// + /// Run make. + /// + /// Arguments. + /// Receives standard output. + /// Receives standard error. + /// Make exit code. + private static int RunMake(string arguments, + out string standardOutput, + out string standardError) + { + string make = "mingw32-make"; + string makeParameters = GetConfigurationOption("makeParameters", ""); + string reactosDirectory = Path.Combine(System.Environment.CurrentDirectory, + "reactos"); + return RunScript(make, + makeParameters + " " + arguments, + reactosDirectory, + GetEnvironmentVarables(), + out standardOutput, + out standardError); + } + + /// + /// Verify a revision of ReactOS by building it all. + /// + private static int VerifyFull() + { + string standardOutput; + string standardError; + int exitCode = RunMake("bootcd", + out standardOutput, + out standardError); + if (exitCode != 0) + { + Fail(String.Format("make bootcd failed: (error: {0}) {1}", + standardError, + standardOutput)); + return exitCode; + } + + string reactosDirectory = Path.Combine(System.Environment.CurrentDirectory, + "reactos"); + string isoFilename = Path.Combine(reactosDirectory, + "ReactOS.iso"); + if (!File.Exists(isoFilename)) + Fail("make bootcd produced no ReactOS.iso"); + + return exitCode; + } + + /// + /// Verify a revision of ReactOS by building parts. + /// + /// Comma separated list of components to build. + private static int VerifyPartial(string components) + { + string standardOutput; + string standardError; + string componentParameters = "\"" + components.Replace(",", "\" \"") + "\""; + int exitCode = RunMake(componentParameters, + out standardOutput, + out standardError); + if (exitCode != 0) + Fail(String.Format("make failed for targets {0}: (error: {1}) {2}", + componentParameters, + standardError, + standardOutput)); + return exitCode; + } + + /// + /// Verify a revision of ReactOS. + /// + /// Arguments from command line. + private static int Verify(string[] args) + { + if (args.Length > 0) + return VerifyPartial(args[0]); + else + return VerifyFull(); + } + + /// + /// Program entry point. + /// + /// Arguments from command line. + /// + /// If exit code is 0, then the commit was processed successfully. + /// If exit code is 1, then the commit was not processed successfully. + /// + public static void Main(string[] args) + { + try + { + System.Environment.ExitCode = Verify(args); + } + catch (Exception ex) + { + string text = String.Format("Exception: {0}", ex); + SendErrorMail("ReactOS Verify Error", text); + System.Environment.ExitCode = 1; + } + } + } +} diff --git a/cis/ReactOS.Verify/RedirectableProcess.cs b/cis/ReactOS.Verify/RedirectableProcess.cs new file mode 100644 index 00000000000..6bdfe94895c --- /dev/null +++ b/cis/ReactOS.Verify/RedirectableProcess.cs @@ -0,0 +1,145 @@ +/* + * When using the ProcessStartInfo.RedirectStandardXxx properties there is a chance of + * the parent and child process blocking due to a race condition. This class handles the + * problem. + * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemdiagnosticsprocessstartinfoclassredirectstandardoutputtopic.asp + */ +using System; +using System.IO; +using System.Threading; +using System.Diagnostics; + +namespace ReactOS.Verify +{ + /// + /// Process that redirects standard output and standard error streams. + /// + public class RedirectableProcess + { + /// + /// Process. + /// + private Process process; + + /// + /// Redirected standard error stream. + /// + private string processError; + + /// + /// Redirected standard output stream. + /// + private string processOutput; + + /// + /// Exit code. + /// + private int exitCode; + + /// + /// Redirected standard error stream. + /// + public string ProcessError + { + get + { + return processError; + } + } + + /// + /// Redirected standard output stream. + /// + public string ProcessOutput + { + get + { + return processOutput; + } + } + + /// + /// Exit code. + /// + public int ExitCode + { + get + { + return exitCode; + } + } + + /// + /// Run an excutable and redirect standard error and/or standard output safely. + /// + public RedirectableProcess(ProcessStartInfo processStartInfo) + { + Run(processStartInfo, null); + } + + /// + /// Run an excutable and redirect standard error and/or standard output safely. + /// + public RedirectableProcess(ProcessStartInfo processStartInfo, string input) + { + Run(processStartInfo, input); + } + + private void Run(ProcessStartInfo processStartInfo, string input) + { + process = new Process(); + process.StartInfo = processStartInfo; + process.Start(); + if (processStartInfo.RedirectStandardInput && input != null) + { + process.StandardInput.AutoFlush = true; + process.StandardInput.WriteLine(input); + } + Thread readStandardError = null; + if (processStartInfo.RedirectStandardError) + { + readStandardError = new Thread(new ThreadStart(ReadStandardError)); + readStandardError.Start(); + } + Thread readStandardOutput = null; + if (processStartInfo.RedirectStandardOutput) + { + readStandardOutput = new Thread(new ThreadStart(ReadStandardOutput)); + readStandardOutput.Start(); + } + if (processStartInfo.RedirectStandardError) + { + readStandardError.Join(); + } + if (processStartInfo.RedirectStandardOutput) + { + readStandardOutput.Join(); + } + process.WaitForExit(); + exitCode = process.ExitCode; + process = null; + } + + /// + /// Read standard error thread entry-point. + /// + private void ReadStandardError() + { + if (process != null) + { + processError = process.StandardError.ReadToEnd(); + } + } + + /// + /// Read standard output thread entry-point. + /// + private void ReadStandardOutput() + { + if (process != null) + { + processOutput = process.StandardOutput.ReadToEnd(); + } + } + } +} -- 2.17.1