Browse Source

Update CheckFileHeaders tool.

pull/1/head
Daniel Grunwald 16 years ago
parent
commit
070d473664
  1. 58
      src/AddIns/Debugger/Debugger.AddIn/license.txt
  2. 20
      src/Tools/CheckFileHeaders/CheckFileHeaders.csproj
  3. 201
      src/Tools/CheckFileHeaders/Main.cs
  4. 30
      src/Tools/CheckFileHeaders/SetSubversionKeywords.txt

58
src/AddIns/Debugger/Debugger.AddIn/COPYING → src/AddIns/Debugger/Debugger.AddIn/license.txt

@ -1,30 +1,30 @@
Copyright (c) 2007, ic#code Copyright (c) 2007-2010, AlphaSierraPapa for the SharpDevelop Team
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met: modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, 1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer. this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright 2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
3. Neither the name of the ic#code nor the names of its contributors may be 3. Neither the name of AlphaSierraPapa nor the names of its contributors may
used to endorse or promote products derived from this software without be used to endorse or promote products derived from this software without
specific prior written permission. specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.

20
src/Tools/CheckFileHeaders/CheckFileHeaders.csproj

@ -1,4 +1,5 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<RootNamespace>CheckFileHeaders</RootNamespace> <RootNamespace>CheckFileHeaders</RootNamespace>
@ -6,6 +7,12 @@
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{1377E452-CBBA-4A41-8F06-F749DC99FE1A}</ProjectGuid> <ProjectGuid>{1377E452-CBBA-4A41-8F06-F749DC99FE1A}</ProjectGuid>
<AllowUnsafeBlocks>False</AllowUnsafeBlocks>
<NoStdLib>False</NoStdLib>
<DebugType>Full</DebugType>
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<DebugSymbols>True</DebugSymbols>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<OutputPath>bin\Debug\</OutputPath> <OutputPath>bin\Debug\</OutputPath>
@ -17,6 +24,16 @@
<Optimize>true</Optimize> <Optimize>true</Optimize>
<DefineConstants>TRACE</DefineConstants> <DefineConstants>TRACE</DefineConstants>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
</PropertyGroup>
<PropertyGroup Condition=" '$(Platform)' == 'AnyCPU' ">
<RegisterForComInterop>False</RegisterForComInterop>
<GenerateSerializationAssemblies>Auto</GenerateSerializationAssemblies>
<BaseAddress>4194304</BaseAddress>
<PlatformTarget>x86</PlatformTarget>
<FileAlignment>4096</FileAlignment>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Data" /> <Reference Include="System.Data" />
@ -24,7 +41,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Main.cs" /> <Compile Include="Main.cs" />
<None Include="SetSubversionKeywords.txt" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" />
</Project> </Project>

201
src/Tools/CheckFileHeaders/Main.cs

@ -1,9 +1,5 @@
// <file> // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// <copyright see="prj:///doc/copyright.txt"/> // This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -15,17 +11,25 @@ namespace CheckFileHeaders
{ {
class MainClass class MainClass
{ {
const string copyrightHeader = @"// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)";
const string licenseHeaderLGPL = @"// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)";
string currentLicense = licenseHeaderLGPL;
static int Main(string[] args) static int Main(string[] args)
{ {
int count;
try { try {
MainClass m = new MainClass(); MainClass m = new MainClass();
int count;
if (args.Length == 0) { if (args.Length == 0) {
Console.WriteLine("Checking files in {0} ...", Path.GetFullPath(@"..\..\..\..\")); Environment.CurrentDirectory = Path.GetFullPath(@"..\..\..\..\..");
count = m.Run(@"..\..\..\..\"); Console.WriteLine("Checking files in {0} ...", Path.GetFullPath("src"));
count = m.Run("src");
} else { } else {
Console.WriteLine("Checking files in {0} ...", Path.GetFullPath(args[0])); Environment.CurrentDirectory = Path.GetFullPath(args[0]);
count = m.Run(args[0]); Console.WriteLine("Checking files in {0} ...", Path.GetFullPath("."));
count = m.Run(".");
} }
Console.WriteLine("Finished! (checked {0} files, changed {1} files, ignored {2} files)", count, m.changeCount, m.ignoreCount); Console.WriteLine("Finished! (checked {0} files, changed {1} files, ignored {2} files)", count, m.changeCount, m.ignoreCount);
} catch (Exception ex) { } catch (Exception ex) {
@ -37,10 +41,14 @@ namespace CheckFileHeaders
} }
int Run(string dir) int Run(string dir)
{ {
string oldLicense = currentLicense;
if (File.Exists(Path.Combine(dir, "license.txt"))) {
if (File.ReadAllText(Path.Combine(dir, "license.txt")).Contains("Redistributions of source code must retain the above copyright notice")) {
currentLicense = @"// This code is distributed under the BSD license (for details please see \" + dir + @"\license.txt)";
}
}
int count = 0; int count = 0;
foreach (string file in Directory.GetFiles(dir, "*.cs")) { foreach (string file in Directory.GetFiles(dir, "*.cs")) {
if (file.EndsWith(".Designer.cs") || file.EndsWith("\\AssemblyInfo.cs"))
continue;
count++; count++;
ProcessFile(file); ProcessFile(file);
} }
@ -57,111 +65,46 @@ namespace CheckFileHeaders
continue; continue;
if (subdir.EndsWith("Libraries\\TreeViewAdv")) if (subdir.EndsWith("Libraries\\TreeViewAdv"))
continue; continue;
if (Path.GetFullPath(subdir).EndsWith("src\\Tools")) if (subdir.EndsWith("Debugger.Core\\Mono.Cecil"))
continue;
// Disabled addins:
if (subdir.EndsWith("AddIns\\Misc\\SharpReport"))
continue;
if (subdir.EndsWith("AddIns\\Misc\\ComponentInspector"))
continue;
if (subdir.EndsWith("AddIns\\BackendBindings\\CppBinding"))
continue; continue;
if (subdir.EndsWith(@"AddIns\BackendBindings\CSharpBinding\Project\Resources")) if (Path.GetFullPath(subdir).EndsWith("src\\Tools"))
continue;
if (subdir.EndsWith(@"Debugger\Debugger.Core\Mono.Cecil"))
continue;
if (subdir.EndsWith(@"AddIns\DisplayBindings\Data"))
continue; continue;
count += Run(subdir); count += Run(subdir);
} }
currentLicense = oldLicense;
return count; return count;
} }
// must be splitted because this file is under version control, too
Regex resetVersionRegex = new Regex(@"// <version>\$Revi" + @"sion: \d+ \$</version>", RegexOptions.Compiled);
int changeCount, ignoreCount; int changeCount, ignoreCount;
void ProcessFile(string file) void ProcessFile(string file)
{ {
string content = GetFileContent(file); string content = GetFileContent(file);
string author, email;
int lastLine; int lastLine;
int headerType = AnalyzeHeader(content, out author, out email, out lastLine); int headerType = AnalyzeHeader(content, out lastLine);
if (headerType == 7)
return;
if (headerType == 5) { if (headerType == 5) {
//Console.WriteLine("unknown file: " + file); Console.WriteLine("unknown file: " + file);
ignoreCount++; ignoreCount++;
return; return;
} }
if (author == null) if (headerType == 6) {
author = ""; Console.WriteLine("file with explicit license: " + file);
if (author == "") { ignoreCount++;
Console.Write(file);
char ch;
do {
Console.WriteLine();
Console.Write(" Daniel/Matt/Other/None/Ignore (D/M/O/N/I): ");
}
while ((ch = char.ToUpper(Console.ReadKey().KeyChar)) != 'M'
&& ch != 'N' && ch != 'I' && ch != 'O' && ch != 'D');
Console.WriteLine();
if (ch == 'M') {
author = "Matthew Ward";
} else if (ch == 'D') {
author = "Daniel Grunwald";
} else if (ch == 'O') {
bool ok;
do {
Console.Write("Enter author name: ");
author = Console.ReadLine();
author = CheckAuthor(author);
ok = author != null;
} while (!ok);
} else if (ch == 'I') {
ignoreCount++;
return;
} else {
author = "unknown";
}
}
string oldAuthor = author;
author = CheckAuthor(author);
if (author == null) {
Console.WriteLine("Unknown author: " + oldAuthor + " in " + file);
Console.WriteLine(" File was ignored.");
return; return;
} }
StringBuilder builder = new StringBuilder();
builder.AppendLine("// <file>");
builder.AppendLine("// <copyright see=\"prj:///doc/copyright.txt\"/>");
if (headerType != 6) { // only if file doesn't have explicit license
builder.AppendLine("// <license see=\"prj:///doc/license.txt\"/>");
}
if (!string.IsNullOrEmpty(email)) { StringBuilder builder = new StringBuilder();
builder.Append("// <owner name=\""); builder.AppendLine(copyrightHeader);
builder.Append(author); builder.AppendLine(currentLicense);
builder.Append("\" email=\""); builder.AppendLine();
builder.Append(email);
} else {
builder.Append("// <author name=\"");
builder.Append(author);
}
builder.AppendLine("\"/>");
// must be splitted because this file is under version control, too
const string versionLine = "// <version>$Revi" + "sion$</version>";
builder.AppendLine(versionLine);
builder.AppendLine("// </file>");
if (headerType != 6) { // only if file doesn't have explicit license
builder.AppendLine();
}
int offset = FindLineOffset(content, lastLine + 1); int offset = FindLineOffset(content, lastLine + 1);
builder.Append(content.Substring(offset).Trim()); builder.Append(content.Substring(offset).Trim());
builder.AppendLine(); builder.AppendLine();
string newContent = builder.ToString(); string newContent = builder.ToString();
string resettedVersion = resetVersionRegex.Replace(content, versionLine); if (newContent.TrimEnd() != content.TrimEnd()) {
if (newContent.TrimEnd() != resettedVersion.TrimEnd()) {
using (StreamWriter w = new StreamWriter(file, false, GetOptimalEncoding(newContent))) { using (StreamWriter w = new StreamWriter(file, false, GetOptimalEncoding(newContent))) {
changeCount++; changeCount++;
w.Write(newContent); w.Write(newContent);
@ -169,57 +112,6 @@ namespace CheckFileHeaders
} }
} }
string CheckAuthor(string author)
{
switch (author) {
case "none":
case "unknown":
return "unknown";
case "David":
case "David Srbecký":
case "David Srbecky":
return "David Srbecký";
case "Peter Forstmeier":
case "Forstmeier Peter":
return "Peter Forstmeier";
case "Daniel":
case "Daniel Grunwald":
return "Daniel Grunwald";
case "Martin":
case "Martin Koníček":
case "Martin Konícek":
return "Martin Koníček";
case "Siegfried":
case "Siegfried Pammer":
return "Siegfried Pammer";
case "Itai Bar-Haim":
case "itai":
return "Itai Bar-Haim";
case "Markus Palme":
case "Mike Krüger":
case "Mathias Simmack":
case "David Alpert":
case "Matthew Ward":
case "Andrea Paatz":
case "Ivan Shumilin":
case "Christian Hornung":
case "Denis ERCHOFF":
case "Georg Brandl":
case "Matt Everson":
case "Shinsaku Nakagawa":
case "Christoph Wille":
case "Robert Zaunere":
case "Justin Dearing":
case "Poul Staugaard":
case "Roman Taranchenko":
case "John Simons":
return author;
default:
return null;
}
}
Encoding GetOptimalEncoding(string content) Encoding GetOptimalEncoding(string content)
{ {
return Encoding.UTF8; return Encoding.UTF8;
@ -250,12 +142,13 @@ namespace CheckFileHeaders
// 4 = unknown header // 4 = unknown header
// 5 = outcommented file // 5 = outcommented file
// 6 = XML header followed by explicit license // 6 = XML header followed by explicit license
int AnalyzeHeader(string content, out string author, out string email, out int lastLine) // 7 = modern header
int AnalyzeHeader(string content, out int lastLine)
{ {
string content2 = content; string content2 = content;
author = null; string author = null;
email = null; string email = null;
int lineNumber = -1; int lineNumber = -1;
lastLine = -1; lastLine = -1;
@ -266,7 +159,6 @@ namespace CheckFileHeaders
// 2 = parse SharpDevelop header // 2 = parse SharpDevelop header
// 3 = search end of GPL header // 3 = search end of GPL header
// 4 = block comment start // 4 = block comment start
// 5 = parse after XML header
using (StringReader r = new StringReader(content)) { using (StringReader r = new StringReader(content)) {
string line; string line;
while ((line = r.ReadLine()) != null) { while ((line = r.ReadLine()) != null) {
@ -275,7 +167,9 @@ namespace CheckFileHeaders
if (state == 0) { if (state == 0) {
if (line.Length == 0) if (line.Length == 0)
continue; continue;
if (line.StartsWith("using ")) { if (line == copyrightHeader) {
return 7;
} else if (line.StartsWith("using ")) {
lastLine = -1; lastLine = -1;
return 0; return 0;
} else if (line == "// <file>") { } else if (line == "// <file>") {
@ -297,7 +191,7 @@ namespace CheckFileHeaders
} else if (state == 1) { } else if (state == 1) {
if (line == "// </file>") { if (line == "// </file>") {
lastLine = lineNumber; lastLine = lineNumber;
state = 5; return 1;
} else if (xmlRegex.IsMatch(line)) { } else if (xmlRegex.IsMatch(line)) {
Match m = xmlRegex.Match(line); Match m = xmlRegex.Match(line);
author = m.Groups[1].Value; author = m.Groups[1].Value;
@ -330,13 +224,6 @@ namespace CheckFileHeaders
} else { } else {
break; break;
} }
} else if (state == 5) {
if (line.Length == 0)
continue;
if (line == "#region License")
return 6;
else
return 1;
} else { } else {
throw new NotSupportedException(); throw new NotSupportedException();
} }

30
src/Tools/CheckFileHeaders/SetSubversionKeywords.txt

@ -1,30 +0,0 @@
For whatever reason, subversion does not do keyword expansion by default. That means that
even if you litter your sources with $Id: $, $Author: $, etc, they will stay as is.
So, even before you begin working with a subversion repository, make the following
changes to your subversion client configuration file:
### Section for configuring miscelleneous Subversion options.
[miscellany]
enable-auto-props = yes
### Section for configuring automatic properties.
[auto-props]
*.cs = svn:keywords=Revision
However, this setting should be done on every developer's workstation (I could not
find a way to enforce it at the repository level, I'd like to be corrected if I'm wrong).
(above text is from http://www.datafaber.com/blog/comments.jsp?contentId=448)
The setting in the config file is only valid for NEW files, to update existing files use:
d:\cygwin\bin\find . -name *.cs -type f -print0 | xargs -0 svn propset svn:keywords "Revision"
(find is usually windows\system32\find.exe; but we need to use the cygwin version here)
Cygwin\bin\find and xargs are cygwin programs: www.cygwin.com
When changing the keywords available, don't forget to use all file extensions that contain the header.
Currently, these are only *.cs files.
Loading…
Cancel
Save