/// <summary> /// Outputs an indented message to the build log if its priority is /// greather than or equal to the <see cref="Threshold" /> of the /// logger. /// </summary> /// <param name="e">The event to output.</param> /// <param name="indentationLength">TODO</param> private void OutputMessage(BuildEventArgs e, int indentationLength) { if (e.MessageLevel >= Threshold) { string txt = e.Message; // beautify the message a bit txt = txt.Replace("\t", " "); // replace tabs with spaces txt = txt.Replace("\r", ""); // get rid of carriage returns // split the message by lines - the separator is "\n" since we've eliminated // \r characters string[] lines = txt.Split('\n'); string label = String.Empty; if (e.Task != null && !EmacsMode) { label = "[" + e.Task.Name + "] "; label = label.PadLeft(e.Project.IndentationSize); } if (indentationLength > 0) { label = new String(' ', indentationLength) + label; } foreach (string line in lines) { StringBuilder sb = new StringBuilder(); sb.Append(label); sb.Append(line); string indentedMessage = sb.ToString(); // output the message to the console Console.Out.WriteLine(indentedMessage); // if an OutputWriter was set, write the message to it if (OutputWriter != null) { OutputWriter.WriteLine(indentedMessage); } Log(indentedMessage); } } }
private static BuildEventArgs CreateBuildEvent(Level messageLevel, string message) { BuildEventArgs buildEvent = new BuildEventArgs(); buildEvent.MessageLevel = messageLevel; buildEvent.Message = message; return buildEvent; }
/// <summary> /// Outputs an indented message to the build log if its priority is /// greather than or equal to the <see cref="Threshold" /> of the /// logger. /// </summary> /// <param name="e">The event to output.</param> private void OutputMessage(BuildEventArgs e) { int indentationLength = 0; if (e.Project != null) { indentationLength = e.Project.IndentationLevel * e.Project.IndentationSize; } OutputMessage(e, indentationLength); }
/// <summary> /// Signals that a task has finished. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">A <see cref="BuildEventArgs" /> object that contains the event data.</param> /// <remarks> /// This event will still be fired if an error occurred during the build. /// </remarks> public virtual void TaskFinished(object sender, BuildEventArgs e) { }
/// <summary> /// Signals that a task has started. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">A <see cref="BuildEventArgs" /> object that contains the event data.</param> public virtual void TaskStarted(object sender, BuildEventArgs e) { }
/// <summary> /// Signals that a message has been logged. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">A <see cref="BuildEventArgs" /> object that contains the event data.</param> /// <remarks> /// Only messages with a priority higher or equal to the threshold of /// the logger will actually be output in the build log. /// </remarks> public virtual void MessageLogged(object sender, BuildEventArgs e) { if (_buildReports.Count > 0) { if (e.MessageLevel == Level.Error) { BuildReport report = (BuildReport) _buildReports.Peek(); report.Errors++; } else if (e.MessageLevel == Level.Warning) { BuildReport report = (BuildReport) _buildReports.Peek(); report.Warnings++; } } // output the message OutputMessage(e); }
/// <summary> /// Signals that a target has started. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">A <see cref="BuildEventArgs" /> object that contains the event data.</param> public virtual void TargetStarted(object sender, BuildEventArgs e) { int indentationLevel = 0; if (e.Project != null) { indentationLevel = e.Project.IndentationLevel * e.Project.IndentationSize; } if (e.Target != null) { OutputMessage(Level.Info, string.Empty, indentationLevel); OutputMessage( Level.Info, string.Format(CultureInfo.InvariantCulture, "{0}:", e.Target.Name), indentationLevel); OutputMessage(Level.Info, string.Empty, indentationLevel); } }
/// <summary> /// Signals that the last target has finished. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">A <see cref="BuildEventArgs" /> object that contains the event data.</param> /// <remarks> /// This event will still be fired if an error occurred during the build. /// </remarks> public virtual void BuildFinished(object sender, BuildEventArgs e) { Exception error = e.Exception; int indentationLevel = 0; if (e.Project != null) { indentationLevel = e.Project.IndentationLevel * e.Project.IndentationSize; } BuildReport report = (BuildReport) _buildReports.Pop(); if (error == null) { OutputMessage(Level.Info, string.Empty, indentationLevel); if (report.Errors == 0 && report.Warnings == 0) { OutputMessage(Level.Info, "BUILD SUCCEEDED", indentationLevel); } else { OutputMessage(Level.Info, string.Format(CultureInfo.InvariantCulture, ResourceUtils.GetString("String_BuildSucceeded"), report.Errors, report.Warnings), indentationLevel); } OutputMessage(Level.Info, string.Empty, indentationLevel); } else { OutputMessage(Level.Error, string.Empty, indentationLevel); if (report.Errors == 0 && report.Warnings == 0) { OutputMessage(Level.Error, "BUILD FAILED", indentationLevel); } else { OutputMessage(Level.Info, string.Format(CultureInfo.InvariantCulture, ResourceUtils.GetString("String_BuildFailed"), report.Errors, report.Warnings), indentationLevel); } OutputMessage(Level.Error, string.Empty, indentationLevel); if (error is BuildException) { if (Threshold <= Level.Verbose) { OutputMessage(Level.Error, error.ToString(), indentationLevel); } else { if (error.Message != null) { OutputMessage(Level.Error, error.Message, indentationLevel); } // output nested exceptions Exception nestedException = error.InnerException; int exceptionIndentationLevel = indentationLevel; int indentShift = 4; //e.Project.IndentationSize; while (nestedException != null && !StringUtils.IsNullOrEmpty(nestedException.Message)) { exceptionIndentationLevel += indentShift; OutputMessage(Level.Error, nestedException.Message, exceptionIndentationLevel); nestedException = nestedException.InnerException; } } } else { OutputMessage(Level.Error, "INTERNAL ERROR", indentationLevel); OutputMessage(Level.Error, string.Empty, indentationLevel); OutputMessage(Level.Error, error.ToString(), indentationLevel); OutputMessage(Level.Error, string.Empty, indentationLevel); OutputMessage(Level.Error, "Please send bug report to [email protected].", indentationLevel); } OutputMessage(Level.Error, string.Empty, indentationLevel); } // output total build time TimeSpan buildTime = DateTime.Now - report.StartTime; OutputMessage(Level.Info, string.Format(CultureInfo.InvariantCulture, ResourceUtils.GetString("String_TotalTime") + Environment.NewLine, Math.Round(buildTime.TotalSeconds, 1)), indentationLevel); // make sure all messages are written to the underlying storage Flush(); }
/// <summary> /// Signals that a build has started. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">A <see cref="BuildEventArgs" /> object that contains the event data.</param> /// <remarks> /// This event is fired before any targets have started. /// </remarks> public virtual void BuildStarted(object sender, BuildEventArgs e) { _buildReports.Push(new BuildReport(DateTime.Now)); }
/// <summary> /// Dispatches a <see cref="TargetStarted" /> event to the build listeners /// for this <see cref="Project" />. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">A <see cref="BuildEventArgs" /> that contains the event data.</param> public void OnTargetStarted(object sender, BuildEventArgs e) { if (TargetStarted != null) { TargetStarted(sender, e); } }
/// <summary> /// Dispatches the <see cref="TaskFinished" /> event to the build listeners /// for this <see cref="Project" />. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">A <see cref="BuildEventArgs" /> that contains the event data.</param> public void OnTaskFinished(object sender, BuildEventArgs e) { if (TaskFinished != null) { TaskFinished(sender, e); } }
/// <summary> /// Dispatches a <see cref="MessageLogged" /> event to the build listeners /// for this <see cref="Project" />. /// </summary> /// <param name="e">A <see cref="BuildEventArgs" /> that contains the event data.</param> public void OnMessageLogged(BuildEventArgs e) { if (MessageLogged != null) { MessageLogged(this, e); } }
/// <summary> /// Dispatches a <see cref="BuildStarted" /> event to the build listeners /// for this <see cref="Project" />. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">A <see cref="BuildEventArgs" /> that contains the event data.</param> public void OnBuildStarted(object sender, BuildEventArgs e) { if (BuildStarted != null) { BuildStarted(sender, e); } }
/// <summary> /// Writes a <see cref="Target" /> level message to the build log with /// the given <see cref="Level" />. /// </summary> /// <param name="target">The <see cref="Target" /> from which the message orignated.</param> /// <param name="messageLevel">The level to log at.</param> /// <param name="message">The message to log.</param> public void Log(Target target, Level messageLevel, string message) { BuildEventArgs eventArgs = new BuildEventArgs(target); eventArgs.Message = message; eventArgs.MessageLevel = messageLevel; OnMessageLogged(eventArgs); }
/// <summary> /// Writes a <see cref="Project" /> level formatted message to the build /// log with the given <see cref="Level" />. /// </summary> /// <param name="messageLevel">The <see cref="Level" /> to log at.</param> /// <param name="message">The message to log, containing zero or more format items.</param> /// <param name="args">An <see cref="object" /> array containing zero or more objects to format.</param> public void Log(Level messageLevel, string message, params object[] args) { BuildEventArgs eventArgs = new BuildEventArgs(this); eventArgs.Message = string.Format(CultureInfo.InvariantCulture, message, args); eventArgs.MessageLevel = messageLevel; OnMessageLogged(eventArgs); }
/// <summary> /// Executes the default target and wraps in error handling and time /// stamping. /// </summary> /// <returns> /// <see langword="true" /> if the build was successful; otherwise, /// <see langword="false" />. /// </returns> public bool Run() { Exception error = null; try { OnBuildStarted(this, new BuildEventArgs(this)); // output build file that we're running Log(Level.Info, "Buildfile: {0}", BuildFileUri); // output current target framework in build log Log(Level.Info, "Target framework: {0}", TargetFramework != null ? TargetFramework.Description : "None"); // write verbose project information after Initialize to make // sure properties are correctly initialized Log(Level.Verbose, "Base Directory: {0}.", BaseDirectory); // execute the project Execute(); // signal build success return true; } catch (BuildException e) { // store exception in error variable in order to include it // in the BuildFinished event. error = e; // log exception details to log4net logger.Error("Build failed.", e); // signal build failure return false; } catch (Exception e) { // store exception in error variable in order to include it // in the BuildFinished event. error = e; // log exception details to log4net logger.Fatal("Build failed.", e); // signal build failure return false; } finally { string endTarget; if (error == null) { endTarget = Properties[CIScriptPropertyOnSuccess]; } else { endTarget = Properties[CIScriptPropertyOnFailure]; } // TO-DO : remove this after release of CIScript 0.8.4 or so string deprecatedFailureTarget = Properties["ciscript.failure"]; if (!StringUtils.IsNullOrEmpty(deprecatedFailureTarget)) { Log(Level.Warning, "The 'ciscript.failure' property has been deprecated." + " You should use '{0}' to designate the target that should be" + " executed when the build fails." + Environment.NewLine, Project.CIScriptPropertyOnFailure); if (error != null) { Execute(deprecatedFailureTarget); } } if (!StringUtils.IsNullOrEmpty(endTarget)) { // executing the target identified by the 'ciscript.onsuccess' // or 'ciscript.onfailure' properties should not affect the // build outcome CallTask callTask = new CallTask(); callTask.Parent = this; callTask.Project = this; callTask.NamespaceManager = NamespaceManager; callTask.Verbose = Verbose; callTask.FailOnError = false; callTask.TargetName = endTarget; callTask.Execute(); } // fire BuildFinished event with details of build outcome BuildEventArgs buildFinishedArgs = new BuildEventArgs(this); buildFinishedArgs.Exception = error; OnBuildFinished(this, buildFinishedArgs); } }