3 using System.Diagnostics;
4 using System.Configuration;
7 namespace ReactOS.CustomRevisionAction
12 /// Path to store published binaries at.
14 private static string publishPath;
17 /// Whether or not to publish ISOs to a remote destination via FTP.
19 private static bool PublishToRemoteFtpLocation
23 return publishPath.StartsWith("ftp://");
28 /// Run the application.
30 /// <param name="script">Script to run.</param>
31 /// <param name="args">Arguments to pass to script.</param>
32 /// <param name="workingDirectory">Working directory.</param>
33 /// <param name="standardOutput">Receives standard output.</param>
34 /// <param name="standardError">Receives standard error.</param>
38 private static int RunScript(string script,
40 string workingDirectory,
41 out string standardOutput,
42 out string standardError)
44 ProcessStartInfo scriptProcessStartInfo = new ProcessStartInfo(script,
46 scriptProcessStartInfo.CreateNoWindow = true;
48 * All standard streams must be redirected.
49 * Otherwise DuplicateHandle() will fail.
51 scriptProcessStartInfo.RedirectStandardInput = true;
52 scriptProcessStartInfo.RedirectStandardError = true;
53 scriptProcessStartInfo.RedirectStandardOutput = true;
54 scriptProcessStartInfo.UseShellExecute = false;
55 scriptProcessStartInfo.WorkingDirectory = workingDirectory;
56 RedirectableProcess redirectableProcess = new RedirectableProcess(scriptProcessStartInfo);
57 standardOutput = redirectableProcess.ProcessOutput;
58 standardError = redirectableProcess.ProcessError;
59 return redirectableProcess.ExitCode;
63 /// Retrieve value of configuration from configuration file.
65 /// <param name="name">Name of configuration option.</param>
66 /// <param name="defaultValue">
67 /// Default value to be returned if the option does not exist.
70 /// Value of configuration option or null if the option does not
71 /// exist and no default value is provided.
73 private static string GetConfigurationOption(string name,
76 if (ConfigurationSettings.AppSettings[name] != null)
77 return ConfigurationSettings.AppSettings[name];
85 /// <param name="subject">Subject of the email.</param>
86 /// <param name="body">Content of the email.</param>
87 private static void SendErrorMail(string subject, string body)
91 string smtpServer = GetConfigurationOption("smtpServer", "localhost");
92 string toEmail = GetConfigurationOption("errorEmail", null);
95 string fromEmail = GetConfigurationOption("fromEmail", null);
96 if (fromEmail == null)
98 MailMessage mm = new MailMessage();
99 mm.Priority = MailPriority.Normal;
102 mm.Subject = subject;
105 mm.BodyFormat = MailFormat.Html;
106 SmtpMail.SmtpServer = smtpServer;
111 Console.Error.WriteLine(ex.Message);
116 /// Fail with an error message.
118 /// <param name="revision">Repository revision.</param>
119 /// <param name="text">Error message.</param>
120 private static void Fail(int revision,
123 Console.WriteLine(text);
124 Console.Error.WriteLine(text);
125 SendErrorMail(String.Format("[{0}] ReactOS Publish Error", revision), text);
129 /// Fail with an error message.
131 /// <param name="text">Error message.</param>
132 private static void Fail(string text)
134 Console.WriteLine(text);
135 Console.Error.WriteLine(text);
136 SendErrorMail("ReactOS Publish Error", text);
140 /// Generate filename of distribution.
142 /// <param name="branch">Branch.</param>
143 /// <param name="revision">Revision.</param>
144 private static string GetDistributionFilename(string branch,
147 return String.Format("ReactOS-{0}-r{1}.iso",
152 private static void SplitRemotePublishPath(string publishPath,
154 out string directory)
156 string searchString = "://";
157 int index = publishPath.IndexOf(searchString);
159 throw new InvalidOperationException();
160 int endOfProtocolIndex = index + searchString.Length;
161 string withoutProtocol = publishPath.Remove(0, endOfProtocolIndex);
162 index = withoutProtocol.IndexOf("/");
165 server = withoutProtocol;
170 server = withoutProtocol.Substring(0, index);
171 directory = withoutProtocol.Remove(0, index + 1);
176 /// Copy ISO to the (remote) destination.
178 /// <param name="sourceFilename">Name of source ISO file to copy.</param>
179 /// <param name="branch">Branch.</param>
180 /// <param name="revision">Revision.</param>
182 /// Structure is ftp://ftp.server.com/whereever/<branch>/ReactOS-<branch>-r<revision>.iso.
184 private static void CopyISOToRemoteFtpDestination(string sourceFilename,
188 string distributionFilename = GetDistributionFilename(branch,
190 string destinationFilename = Path.Combine(Path.GetDirectoryName(sourceFilename),
191 distributionFilename);
192 File.Move(sourceFilename, destinationFilename);
195 SplitRemotePublishPath(publishPath, out server, out directory);
196 FtpClient ftpClient = new FtpClient(server, "anonymous", "sin@svn.reactos.com");
199 ftpClient.ChangeDir(directory);
200 /* Create destination directory if it does not already exist */
201 if (!ftpClient.DirectoryExists(branch))
202 ftpClient.MakeDir(branch);
203 ftpClient.ChangeDir(branch);
204 ftpClient.Upload(destinationFilename);
209 /// Copy ISO to the (local) destination.
211 /// <param name="sourceFilename">Name of source ISO file to copy.</param>
212 /// <param name="branch">Branch.</param>
213 /// <param name="revision">Revision.</param>
215 /// Structure is <branch>\ReactOS-<branch>-r<revision>.iso.
217 private static void CopyISOToLocalDestination(string sourceFilename,
221 string distributionFilename = GetDistributionFilename(branch,
223 string destinationDirectory = Path.Combine(publishPath,
225 string destinationFilename = Path.Combine(destinationDirectory,
226 distributionFilename);
227 if (!Directory.Exists(destinationDirectory))
228 Directory.CreateDirectory(destinationDirectory);
229 File.Copy(sourceFilename,
230 destinationFilename);
234 /// Copy ISO to the destination.
236 /// <param name="sourceFilename">Name of source ISO file to copy.</param>
237 /// <param name="branch">Branch.</param>
238 /// <param name="revision">Revision.</param>
240 /// Structure is <branch>\ReactOS-<branch>-r<revision>.iso.
242 private static void CopyISOToDestination(string sourceFilename,
246 if (PublishToRemoteFtpLocation)
247 CopyISOToRemoteFtpDestination(sourceFilename, branch, revision);
249 CopyISOToLocalDestination(sourceFilename, branch, revision);
253 /// Publish a revision of ReactOS.
255 /// <param name="text">Error message.</param>
256 private static int Publish(string branch,
258 string workingDirectory)
260 string make = "mingw32-make";
261 string makeParameters = GetConfigurationOption("makeParameters", "");
262 string reactosDirectory = Path.Combine(workingDirectory,
264 Console.WriteLine(String.Format("ReactOS directory is {0}",
266 string standardOutput;
267 string standardError;
268 int exitCode = RunScript(make,
269 makeParameters + " bootcd",
276 String.Format("make bootcd failed: (error: {0}) {1}",
282 string sourceFilename = Path.Combine(reactosDirectory,
284 if (File.Exists(sourceFilename))
285 CopyISOToDestination(sourceFilename,
291 "make bootcd produced no ReactOS.iso");
299 /// Program entry point.
301 /// <param name="args">Arguments from command line.</param>
303 /// If exit code is 0, then the commit was processed successfully.
304 /// If exit code is 1, then the commit was not processed successfully.
306 public static void Main(string[] args)
310 System.Environment.ExitCode = 1;
312 publishPath = ConfigurationSettings.AppSettings["publishPath"];
313 if (publishPath == null)
315 Fail("PublishPath option not set.");
321 Fail("Usage: ReactOS.CustomRevisionAction action branch revision");
325 string action = args[0]; /* bootcd */
326 string branch = args[1];
327 int revision = Int32.Parse(args[2]);
329 System.Environment.ExitCode = Publish(branch,
331 System.Environment.CurrentDirectory);
335 Fail(String.Format("Exception: {0}", ex));
336 System.Environment.ExitCode = 1;