Created
April 20, 2015 21:49
-
-
Save Deiz/32322020f76d23e2bf8f to your computer and use it in GitHub Desktop.
Script for updating copyright notices
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env perl | |
# vim:ts=4:sw=4:expandtab | |
# | |
# © 2015 Sean Hildebrand | |
# | |
# Licensed under the Apache License, Version 2.0 (the "License"); | |
# you may not use this file except in compliance with the License. | |
# You may obtain a copy of the License at | |
# | |
# http://www.apache.org/licenses/LICENSE-2.0 | |
# | |
# Unless required by applicable law or agreed to in writing, software | |
# distributed under the License is distributed on an "AS IS" BASIS, | |
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
# See the License for the specific language governing permissions and | |
# limitations under the License. | |
# | |
# This script iterates through the specified files, checking for copyright | |
# notices in the form of '© YYYY-YYYY ' and '© YYYY ' and updates them if the | |
# replaces them with '© YYYY ' notices reflecting the year of the first commit | |
# that touched that file, or the original notice's year, whichever is older. | |
# | |
# The script should only be invoked on versioned files, for example: | |
# git ls-files -z | xargs -0 update-copyrights.pl | |
use strict; | |
use warnings; | |
use utf8; | |
# Build the file list by searching for files that contain copyright notices. | |
my (@files, %years, @years); | |
for my $file (@ARGV) { | |
open my $fh, '<', $file or die "Could not open file '$file' for reading"; | |
while (<$fh>) { | |
# Skip lines that aren't formatted as '© YYYY ' or '© YYYY-YYYY ' | |
next unless /© \d{4}(?:-\d{4})? /; | |
# Get the year of the first commit that touched the file. | |
open my $gfh, '-|', qw(git --no-pager log -1 --diff-filter=A | |
--no-merges --follow --format=%ai --), $file; | |
my $first = <$gfh>; | |
close $gfh; | |
if (not defined $first) { | |
printf "File '%s' is not under version control\n", $file; | |
last; | |
} | |
$years{$file} = substr $first, 0, 4; | |
push @files, $file; | |
last; | |
} | |
close $fh; | |
} | |
# Do a second pass to exclude files that don't need to be modified. | |
# A C-style loop is used so the array can be shifted down while iterating. | |
for (my $i=0; $i<@files; $i++) { | |
my $file = $files[$i]; | |
open my $fh, '<', $file or die "Could not open file '$file' for reading"; | |
while (<$fh>) { | |
if ((/© (\d{4}) / and $1 > $years{$file}) or /© \d{4}-\d{4} /) { | |
push @years, $years{$file}; | |
last; | |
} | |
elsif (eof) { | |
splice @files, $i, 1; | |
$i--; | |
} | |
} | |
close $fh; | |
} | |
@ARGV = @files; | |
exit unless @ARGV; | |
$^I = ''; # Enable in-place editing for files. | |
my $year = shift @years; | |
while (defined($_ = <ARGV>)) { | |
$year = shift @years if eof; | |
# Update '© YYYY ' if the notice is newer than the first commit. | |
if (/© (\d{4}) / and $1 > $year) { | |
s/(© \d{4}) /© $year /; | |
} | |
# Replace '© YYYY-YYYY ' ranges with the initial year alone. | |
elsif (/© (\d{4})-(\d{4}) /) { | |
if ($1 > $year) { | |
# First commit is older than range start. | |
s/© \d{4}-\d{4} /© $year /; | |
} | |
else { | |
# Use the original range start instead of the first commit's year. | |
s/(© \d{4})-\d{4} /$1 /; | |
} | |
} | |
print; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment