| #!/usr/bin/perl -w |
| |
| # Copyright (C) 2006, 2007 Apple Inc. All rights reserved. |
| # |
| # Redistribution and use in source and binary forms, with or without |
| # modification, are permitted provided that the following conditions |
| # are met: |
| # |
| # 1. Redistributions of source code must retain the above copyright |
| # notice, this list of conditions and the following disclaimer. |
| # 2. Redistributions in binary form must reproduce the above copyright |
| # notice, this list of conditions and the following disclaimer in the |
| # documentation and/or other materials provided with the distribution. |
| # 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of |
| # its contributors may be used to endorse or promote products derived |
| # from this software without specific prior written permission. |
| # |
| # THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY |
| # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| # DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
| # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| # ON ANY THEORY OF LIABILITY, WHETHER IN 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 POSSIBILITY OF SUCH DAMAGE. |
| |
| # Script to put change log comments in as default check-in comment. |
| |
| use strict; |
| use File::Basename; |
| use File::Spec; |
| use FindBin; |
| use lib $FindBin::Bin; |
| use VCSUtils; |
| use webkitdirs; |
| |
| my $log = $ARGV[0]; |
| |
| my $baseDir = baseProductDir(); |
| |
| my $editor = $ENV{SVN_LOG_EDITOR}; |
| if (!$editor) { |
| $editor = $ENV{CVS_LOG_EDITOR}; |
| } |
| if (!$editor) { |
| my $builtEditorApplication = "$baseDir/Release/Commit Log Editor.app/Contents/MacOS/Commit Log Editor"; |
| $editor = $builtEditorApplication if -x $builtEditorApplication; |
| } |
| if (!$editor) { |
| my $builtEditorApplication = "$baseDir/Debug/Commit Log Editor.app/Contents/MacOS/Commit Log Editor"; |
| $editor = $builtEditorApplication if -x $builtEditorApplication; |
| } |
| if (!$editor) { |
| my $installedEditorApplication = "$ENV{HOME}/Applications/Commit Log Editor.app/Contents/MacOS/Commit Log Editor"; |
| $editor = $installedEditorApplication if -x $installedEditorApplication; |
| } |
| if (!$editor) { |
| $editor = $ENV{EDITOR} || "/usr/bin/vi"; |
| } |
| |
| my $inChangesToBeCommitted = !isGit(); |
| my @changeLogs = (); |
| my $logContents = ""; |
| my $existingLog = 0; |
| open LOG, $log or die; |
| while (<LOG>) { |
| if (isGit()) { |
| if (/^# Changes to be committed:$/) { |
| $inChangesToBeCommitted = 1; |
| } elsif ($inChangesToBeCommitted && /^# \S/) { |
| $inChangesToBeCommitted = 0; |
| } |
| } |
| |
| $logContents .= $_; |
| $existingLog = isGit() && !(/^#/ || /^\s*$/) unless $existingLog; |
| |
| push @changeLogs, makeFilePathRelative($1) if $inChangesToBeCommitted && (/^M....(.*ChangeLog)$/ || /^#\tmodified: (.*ChangeLog)/) && !/-ChangeLog/; |
| } |
| close LOG; |
| |
| # Don't change anything if there's already a log message |
| # (as can happen with git-commit --amend) |
| exec $editor, @ARGV if $existingLog; |
| |
| my $topLevel = topLevelSourceDirectory(); |
| |
| my %changeLogSort; |
| my %changeLogContents; |
| for my $changeLog (@changeLogs) { |
| open CHANGELOG, $changeLog or die "Can't open $changeLog"; |
| my $contents = ""; |
| my $blankLines = ""; |
| while (<CHANGELOG>) { |
| if (/^\S/) { |
| last if $contents; |
| } |
| if (/\S/) { |
| $contents .= $blankLines if $contents; |
| $blankLines = ""; |
| $contents .= $_; |
| } else { |
| $blankLines .= $_; |
| } |
| } |
| close CHANGELOG; |
| |
| $changeLog = File::Spec->abs2rel(File::Spec->rel2abs($changeLog), $topLevel); |
| |
| my $label = dirname($changeLog); |
| $label = "top level" unless length $label; |
| |
| my $sortKey = lc $label; |
| if ($label eq "top level") { |
| $sortKey = ""; |
| } elsif ($label eq "Tools") { |
| $sortKey = "-, just after top level"; |
| } elsif ($label eq "WebBrowser") { |
| $sortKey = lc "WebKit, WebBrowser after"; |
| } elsif ($label eq "WebCore") { |
| $sortKey = lc "WebFoundation, WebCore after"; |
| } elsif ($label eq "LayoutTests") { |
| $sortKey = lc "~, LayoutTests last"; |
| } |
| |
| $changeLogSort{$sortKey} = $label; |
| $changeLogContents{$label} = $contents; |
| } |
| |
| my $first = 1; |
| open NEWLOG, ">$log.edit" or die; |
| for my $sortKey (sort keys %changeLogSort) { |
| my $label = $changeLogSort{$sortKey}; |
| if (keys %changeLogSort > 1) { |
| print NEWLOG "\n" if !$first; |
| $first = 0; |
| print NEWLOG "$label:\n\n"; |
| } |
| print NEWLOG $changeLogContents{$label}; |
| } |
| print NEWLOG $logContents; |
| close NEWLOG; |
| |
| system $editor, "$log.edit"; |
| |
| open NEWLOG, "$log.edit" or exit; |
| my $foundComment = 0; |
| while (<NEWLOG>) { |
| $foundComment = 1 if (/\S/ && !/^CVS:/); |
| } |
| close NEWLOG; |
| |
| if ($foundComment) { |
| open NEWLOG, "$log.edit" or die; |
| open LOG, ">$log" or die; |
| while (<NEWLOG>) { |
| print LOG; |
| } |
| close LOG; |
| close NEWLOG; |
| } |
| |
| unlink "$log.edit"; |
| |
| sub topLevelSourceDirectory |
| { |
| if (isGit()) { |
| chomp(my $gitDir = `git rev-parse --git-dir`); |
| return dirname($gitDir); |
| } elsif (isSVN()) { |
| open(INFO, "-|", qw(svn info)) or die; |
| my ($root, $url); |
| while (my $line = <INFO>) { |
| if ($line =~ /^Repository Root: (.*)$/) { |
| $root = $1; |
| } elsif ($line =~ /^URL: (.*)$/) { |
| $url = $1; |
| } |
| } |
| close(INFO); |
| |
| my $path = $url; |
| $path =~ s/^\Q$root\E//; |
| $path =~ s/^\/?(branches\/[^\/]*|trunk)\/?//; |
| return File::Spec->rel2abs(File::Spec->catdir(map { ".." } File::Spec->splitdir($path))); |
| } |
| } |