Skip to content

Commit 5abe2f9

Browse files
author
Evengard
committed
Original version commit, without changes
1 parent a95e3af commit 5abe2f9

File tree

7 files changed

+602
-0
lines changed

7 files changed

+602
-0
lines changed

Logger.cs

Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
// Copyright © 2006 by Christian Rodemeyer (mailto:christian@atombrenner.de)
2+
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Globalization;
6+
using System.Xml;
7+
8+
using Microsoft.Build.Framework;
9+
using Microsoft.Build.Utilities;
10+
using System.IO;
11+
using System.Collections;
12+
13+
namespace Rodemeyer.MsBuildToCCNet
14+
{
15+
/// <summary>
16+
/// Implements a custom MSBuild logger for integration into CruiseControl.NET
17+
/// The following MSBuild verbosity options (/v:) are supported
18+
/// - Quiet => errors, warnings and number of projects build
19+
/// - Minimal => errors, warnings, one entry for every project
20+
/// - Normal => like Minimal plus messages with high importance
21+
/// - Detailed => like Normal plus messages with normal importance
22+
/// - Diagnostic => like Detailed plus messages with low importance
23+
/// </summary>
24+
public class MsBuildToCCNetLogger : Logger
25+
{
26+
public MsBuildToCCNetLogger()
27+
{ }
28+
29+
private string logfile;
30+
private string commonPrefix;
31+
private int commonPrefixLength;
32+
MessageImportance loglevel;
33+
34+
private Dictionary<string, Project> file_to_project = new Dictionary<string, Project>();
35+
private Stack<Project> project_stack = new Stack<Project>();
36+
private List<Project> projects = new List<Project>();
37+
private Project current_project;
38+
39+
/// <summary>
40+
/// called by MSBuild just before starting the build
41+
/// </summary>
42+
/// <param name="eventSource"></param>
43+
public override void Initialize(IEventSource eventSource)
44+
{
45+
if (base.Parameters != null)
46+
this.logfile = base.Parameters.Split(';')[0]; // ignore all parameters but the first (which is the name of the file to log to)
47+
else
48+
this.logfile = "msbuild-output.xml"; // default, in case we are not startet from a ccnet task
49+
50+
this.commonPrefix = Environment.CurrentDirectory;
51+
this.commonPrefixLength = commonPrefix.Length + 1;
52+
53+
current_project = new Project("MSBuild");
54+
projects.Add(current_project);
55+
project_stack.Push(current_project);
56+
57+
if (this.Verbosity > LoggerVerbosity.Minimal)
58+
{
59+
eventSource.MessageRaised += new BuildMessageEventHandler(OnMessageRaised);
60+
switch (Verbosity)
61+
{
62+
case LoggerVerbosity.Normal: loglevel = MessageImportance.High; break;
63+
case LoggerVerbosity.Detailed: loglevel = MessageImportance.Normal; break;
64+
default: loglevel = MessageImportance.Low; break;
65+
}
66+
}
67+
eventSource.WarningRaised += new BuildWarningEventHandler(OnWarningRaised);
68+
eventSource.ErrorRaised += new BuildErrorEventHandler(OnErrorRaised);
69+
eventSource.ProjectStarted += new ProjectStartedEventHandler(OnProjectStarted);
70+
eventSource.ProjectFinished += new ProjectFinishedEventHandler(OnProjectFinished);
71+
}
72+
73+
/// <summary>
74+
/// called by MSBuild after the build has finished
75+
/// </summary>
76+
public override void Shutdown()
77+
{
78+
XmlTextWriter w = new XmlTextWriter(logfile, System.Text.Encoding.UTF8);
79+
w.Formatting = this.Verbosity > LoggerVerbosity.Quiet ? Formatting.Indented : Formatting.None;
80+
WriteLog(w);
81+
w.Flush();
82+
w.Close();
83+
}
84+
85+
/// <summary>
86+
/// Needed for sorting the project list by number of warnings
87+
/// </summary>
88+
class WarningComparer : IComparer<Project>
89+
{
90+
public int Compare(Project x, Project y)
91+
{
92+
return y.WarningCount - x.WarningCount;
93+
}
94+
}
95+
96+
/// <summary>
97+
/// writes the in memory gathered information into the xml log file
98+
/// </summary>
99+
/// <param name="w"></param>
100+
private void WriteLog(XmlWriter w)
101+
{
102+
w.WriteStartDocument();
103+
w.WriteStartElement("msbuild");
104+
w.WriteAttributeString("project_count", XmlConvert.ToString(projects.Count));
105+
106+
int errorCount = 0;
107+
int warningCount = 0;
108+
foreach (Project p in projects)
109+
{
110+
errorCount += p.ErrorCount;
111+
warningCount += p.WarningCount;
112+
}
113+
w.WriteAttributeString("warning_count", XmlConvert.ToString(warningCount));
114+
w.WriteAttributeString("error_count", XmlConvert.ToString(errorCount));
115+
buildHasErrors = errorCount > 0;
116+
if (!buildHasErrors) // Sort after WarningCount
117+
{
118+
projects.Sort(new WarningComparer());
119+
}
120+
foreach (Project p in projects)
121+
{
122+
if (Verbosity > LoggerVerbosity.Quiet || p.ErrorCount > 0 || p.WarningCount > 0)
123+
{
124+
WriteProject(w, p);
125+
}
126+
}
127+
w.WriteEndElement();
128+
w.WriteEndDocument();
129+
}
130+
131+
private bool buildHasErrors;
132+
133+
/// <summary>
134+
/// removes the working folder from the filename
135+
/// </summary>
136+
/// <param name="file"></param>
137+
/// <returns></returns>
138+
private string RemoveCommonPrefix(string file)
139+
{
140+
if (file.StartsWith(commonPrefix))
141+
return file.Substring(commonPrefixLength, file.Length - commonPrefixLength);
142+
else
143+
return file;
144+
}
145+
146+
private void WriteProject(XmlWriter w, Project p)
147+
{
148+
w.WriteStartElement("project");
149+
string file = RemoveCommonPrefix(p.File);
150+
w.WriteAttributeString("dir", Path.GetDirectoryName(file));
151+
w.WriteAttributeString("name", Path.GetFileName(file));
152+
WriteErrorsOrWarnings(w, "error", p.Errors);
153+
if (!buildHasErrors) WriteErrorsOrWarnings(w, "warning", p.Warnings);
154+
WriteMessages(w, p.Messages);
155+
w.WriteEndElement();
156+
}
157+
158+
private void WriteErrorsOrWarnings(XmlWriter w, string type, IEnumerable list)
159+
{
160+
foreach (ErrorOrWarningBase ew in list)
161+
{
162+
w.WriteStartElement(type);
163+
w.WriteAttributeString("code", ew.Code);
164+
w.WriteAttributeString("message", ew.Text);
165+
if (ew.File != null)
166+
{
167+
w.WriteAttributeString("dir", Path.GetDirectoryName(ew.File));
168+
w.WriteAttributeString("name", Path.GetFileName(ew.File));
169+
w.WriteAttributeString("pos", "(" + XmlConvert.ToString(ew.Line) + ", " + XmlConvert.ToString(ew.Column) + ")");
170+
}
171+
w.WriteEndElement();
172+
}
173+
}
174+
175+
private void WriteMessages(XmlWriter w, IEnumerable<Message> list)
176+
{
177+
foreach (Message m in list)
178+
{
179+
w.WriteStartElement("message");
180+
w.WriteAttributeString("importance", m.Importance.ToString());
181+
w.WriteString(m.Text);
182+
w.WriteEndElement();
183+
}
184+
}
185+
186+
private void OnProjectStarted(object sender, ProjectStartedEventArgs e)
187+
{
188+
if (!file_to_project.TryGetValue(e.ProjectFile, out this.current_project))
189+
{
190+
current_project = new Project(e.ProjectFile);
191+
file_to_project.Add(e.ProjectFile, current_project);
192+
projects.Add(current_project);
193+
}
194+
project_stack.Push(current_project);
195+
}
196+
197+
void OnProjectFinished(object sender, ProjectFinishedEventArgs e)
198+
{
199+
project_stack.Pop();
200+
current_project = (project_stack.Count == 0) ? null : project_stack.Peek();
201+
}
202+
203+
private void OnWarningRaised(object sender, BuildWarningEventArgs e)
204+
{
205+
current_project.Add(new Warning(e));
206+
}
207+
208+
private void OnErrorRaised(object sender, BuildErrorEventArgs e)
209+
{
210+
current_project.Add(new Error(e));
211+
}
212+
213+
private void OnMessageRaised(object sender, BuildMessageEventArgs e)
214+
{
215+
if (e.Importance <= loglevel)
216+
{
217+
current_project.Add(new Message(e));
218+
}
219+
}
220+
221+
}
222+
223+
}

MsBuildToCCNet.csproj

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
2+
<PropertyGroup>
3+
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
4+
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
5+
<ProductVersion>8.0.50727</ProductVersion>
6+
<SchemaVersion>2.0</SchemaVersion>
7+
<ProjectGuid>{E9D3235E-2268-4846-B9EC-DFE24AAA438D}</ProjectGuid>
8+
<OutputType>Library</OutputType>
9+
<AppDesignerFolder>Properties</AppDesignerFolder>
10+
<RootNamespace>Rodemeyer.MsBuildToCCnet</RootNamespace>
11+
<AssemblyName>Rodemeyer.MsBuildToCCnet</AssemblyName>
12+
<SccProjectName>
13+
</SccProjectName>
14+
<SccLocalPath>
15+
</SccLocalPath>
16+
<SccAuxPath>
17+
</SccAuxPath>
18+
<SccProvider>
19+
</SccProvider>
20+
</PropertyGroup>
21+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
22+
<DebugSymbols>true</DebugSymbols>
23+
<DebugType>full</DebugType>
24+
<Optimize>false</Optimize>
25+
<OutputPath>bin\Debug\</OutputPath>
26+
<DefineConstants>DEBUG;TRACE</DefineConstants>
27+
<ErrorReport>prompt</ErrorReport>
28+
<WarningLevel>4</WarningLevel>
29+
</PropertyGroup>
30+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
31+
<DebugType>none</DebugType>
32+
<Optimize>true</Optimize>
33+
<OutputPath>bin\Release\</OutputPath>
34+
<DefineConstants>TRACE</DefineConstants>
35+
<ErrorReport>prompt</ErrorReport>
36+
<WarningLevel>4</WarningLevel>
37+
</PropertyGroup>
38+
<ItemGroup>
39+
<Reference Include="Microsoft.Build.Framework" />
40+
<Reference Include="Microsoft.Build.Utilities" />
41+
<Reference Include="System" />
42+
<Reference Include="System.Data" />
43+
<Reference Include="System.Xml" />
44+
</ItemGroup>
45+
<ItemGroup>
46+
<Compile Include="Project.cs" />
47+
<Compile Include="Properties\AssemblyInfo.cs" />
48+
<Compile Include="Logger.cs" />
49+
</ItemGroup>
50+
<ItemGroup>
51+
<Content Include="ccnet\cruisecontrol.css" />
52+
</ItemGroup>
53+
<ItemGroup>
54+
<Content Include="ccnet\msbuild2ccnet.xsl" />
55+
</ItemGroup>
56+
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
57+
</Project>

MsBuildToCCnet.sln

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 9.00
3+
# Visual Studio 2005
4+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MsBuildToCCNet", "MsBuildToCCNet.csproj", "{E9D3235E-2268-4846-B9EC-DFE24AAA438D}"
5+
EndProject
6+
Global
7+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
8+
Debug|Any CPU = Debug|Any CPU
9+
Release|Any CPU = Release|Any CPU
10+
EndGlobalSection
11+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
12+
{E9D3235E-2268-4846-B9EC-DFE24AAA438D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
13+
{E9D3235E-2268-4846-B9EC-DFE24AAA438D}.Debug|Any CPU.Build.0 = Debug|Any CPU
14+
{E9D3235E-2268-4846-B9EC-DFE24AAA438D}.Release|Any CPU.ActiveCfg = Release|Any CPU
15+
{E9D3235E-2268-4846-B9EC-DFE24AAA438D}.Release|Any CPU.Build.0 = Release|Any CPU
16+
EndGlobalSection
17+
GlobalSection(SolutionProperties) = preSolution
18+
HideSolutionNode = FALSE
19+
EndGlobalSection
20+
EndGlobal

0 commit comments

Comments
 (0)