"The source code is already in an SCM. Do I need to ask the person to modify every single file by himself, or can I somehow make it less work for him?"
I actually had this same problem on a old project. I eventually broke down and just wrote a little tool to replace the licenses automatically. It took a file containing the license and injected the text into all the .cs files (it was a c# project) it found in a given directory and all of its subdirs after stripping them of their old one (it just looked for a beginning comment...it was quick and dirty).
Here it is, in c#. Distributed under MIT/X11 :
/*
Copyright (c) 2009 Benjamin J. Setel
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
using System.IO;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System;
namespace Tools
{
class LicenseInjector
{
public static void Main()
{
Console.WriteLine("Please enter the full root folder path (i.e. /home/usr/code/): ");
string folder = Console.ReadLine();
Console.WriteLine("Please enter full path to license data: ");
string LicensePath = Console.ReadLine();
FileStream ReadFile = new FileStream(LicensePath, FileMode.Open, FileAccess.Read);
StreamReader sr = new StreamReader(ReadFile);
string license = sr.ReadToEnd();
sr.Close();
ReadFile.Close();
Recursion.RecursivePrepend(folder, license);
}//Main
}//LicenseInjector
public static class Recursion
{
public static void RecursivePrepend(string folder, string license)
{
string [] Subdirs = Directory.GetDirectories(folder);
if(Subdirs.Length != 0)
{
foreach(string s in Subdirs)
RecursivePrepend(s, license);
}
string[] files = PatternFind.DirPatternFinder(folder, ".cs");
foreach(string s in files)
Prepend.Prepender(s, license);
}//RecursivePrepend()
}//Recursion
public static class PatternFind
{
public static string[] DirPatternFinder(string ToLook, string Pattern)
{
Regex r = new Regex(Pattern);
string[] files = Directory.GetFiles(ToLook);
List<string> results = new List<string>();
for(int i = 0; i < files.Length; ++i)
{
Match m = r.Match(files[i]);
if(m.Success)
results.Add(files[i]);
}
return results.ToArray();
}//DirPatternFinder()
public static string PatternFinder(string Pattern1, string Pattern2)
{
Regex r = new Regex(Pattern1);
Match m = r.Match(Pattern2);
return m.ToString();
}//PatternFinder()
}//PatternFind
public static class Prepend
{
public static void Prepender(string path, string ToPut)
{
FileStream ReadFile = new FileStream(path, FileMode.Open, FileAccess.Read);
StreamReader sr = new StreamReader(ReadFile);
string s = sr.ReadToEnd();
sr.Close();
ReadFile.Close();
bool HasLicense = false;
if(s.Substring(0, 2) == "/*")
HasLicense = true;
if(HasLicense) //If the file already has the license, we have to strip it out before adding it back in
// so that the file does not wind up with more than one copy.
{
int i = 1;
string c = "(";
while(c != "*/" && i < s.Length)
{
c = s.Substring(i, 2);
++i;
}
if(String.Compare("\n\n", s.Substring(i+1, 2)) == 0) //If there's already a newline after the license
{
s = s.Remove(0, i+3);
}
else
{
s = s.Remove(0, i+2);
}
}
FileStream WriteFile = new FileStream(path, FileMode.Open, FileAccess.Write);
StreamWriter FileWriter = new StreamWriter(WriteFile);
FileWriter.Write(ToPut);
FileWriter.Write("\n");
FileWriter.Write(s);
FileWriter.Close();
WriteFile.Close();
return;
}//Prepender()
}//Prepend
}//Tools