ReactOS Sin Verifier
authorCasper Hornstrup <chorns@users.sourceforge.net>
Wed, 23 Nov 2005 17:25:55 +0000 (17:25 +0000)
committerCasper Hornstrup <chorns@users.sourceforge.net>
Wed, 23 Nov 2005 17:25:55 +0000 (17:25 +0000)
svn path=/trunk/; revision=19490

cis/ReactOS.Verify/App.config [new file with mode: 0644]
cis/ReactOS.Verify/AssemblyInfo.cs [new file with mode: 0644]
cis/ReactOS.Verify/Default.build [new file with mode: 0644]
cis/ReactOS.Verify/Main.cs [new file with mode: 0644]
cis/ReactOS.Verify/RedirectableProcess.cs [new file with mode: 0644]

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