1#! /usr/bin/env perl 2 3# colorsvn 4# 5# based on colorgcc 6# 7# Requires the ANSIColor module from CPAN. 8# 9# Usage: 10# 11# In a directory that occurs in your PATH _before_ the directory 12# where svn lives, create a softlink to colorsvn: 13# 14# svn -> colorsvn 15# 16# That's it. When "svn" is invoked, colorsvn is run instead. 17# 18# The default settings can be overridden with ~/.colorcvsrc. 19# See the colorcvsrc-sample for more information. 20# 21# Note: 22# 23# colorsvn will only emit color codes if: 24# 25# (1) tts STDOUT is a tty. 26# (2) the value of $TERM is not listed in the "nocolor" option. 27# (3) the svn command is not a commit or import (as the text editor 28# opened by svn will often be hampered by colorsvn). 29# 30# If colorsvn colorizes the output, svn's STDERR will be 31# combined with STDOUT. Otherwise, colorsvn just passes the output from 32# svn through without modification. 33# 34# Copyright 2002 Neil Stevens <neil@qualityassistant.com> 35# 36# Copyright 1999 Jamie Moyers <jmoyers@geeks.com> 37# 38# This program is free software; you can redistribute it and/or modify 39# it under the terms of the GNU General Public License as published by 40# the Free Software Foundation; version 2 of the License as published 41# by the Free Software Foundation. 42# 43# This program is distributed in the hope that it will be useful, 44# but WITHOUT ANY WARRANTY; without even the implied warranty of 45# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 46# GNU General Public License for more details. 47# 48# You should have received a copy of the GNU General Public License 49# along with this program; if not, write to the Free Software 50# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 51 52use Term::ANSIColor; 53use IPC::Open3; 54use File::Spec::Functions qw/catfile file_name_is_absolute path/; 55 56sub initDefaults 57{ 58 $svnCmd = "svn"; 59 60 $nocolor{"dumb"} = "true"; 61 62 $colors{"P"} = color("reset"); 63 $colors{"U"} = color("reset"); 64 $colors{" "} = color("reset"); 65 $colors{"C"} = color("bold red"); 66 $colors{"M"} = color("bold yellow"); 67 $colors{'G'} = color("bold yellow"); 68 $colors{"A"} = color("cyan"); 69 $colors{"R"} = color("cyan"); 70 $colors{"D"} = color("red"); 71 $colors{"I"} = color("bold"); 72 $colors{"?"} = color("bold"); 73 $colors{"!"} = color("bold"); 74 $colors{"~"} = color("bold red"); 75 $colors{"server"} = color("bold green"); 76 $colors{"warning"} = color("bold cyan"); 77 78 # Applies when only the properties changed 79 $propcolors{"C"} = color("bold red"); 80 $propcolors{"M"} = color("yellow"); 81} 82 83sub loadPreferences 84{ 85# Usage: loadPreferences("filename"); 86 87 my($filename) = @_; 88 89 open(PREFS, "<$filename") || return; 90 91 while(<PREFS>) 92 { 93 next if (m/^\#.*/); # It's a comment. 94 next if (!m/(.*):\s*(.*)/); # It's not of the form "foo: bar". 95 96 $option = $1; 97 $value = $2; 98 99 if ($option =~ /svn/) 100 { 101 $svnCmd = $value; 102 } 103 elsif ($option eq "nocolor") 104 { 105 # The nocolor option lists terminal types, separated by 106 # spaces, not to do color on. 107 foreach $termtype (split(/\s+/, $value)) 108 { 109 $nocolor{$termtype} = "true"; 110 } 111 } 112 elsif ($option =~ /prop (.)/) 113 { 114 # Property color 115 $propcolors{$1} = color($value); 116 } 117 else 118 { 119 $colors{$option} = color($value); 120 } 121 } 122 close(PREFS); 123} 124 125# 126# Main program 127# 128 129# Set up default values for colors and svn path. 130initDefaults(); 131 132# Read the configuration file, if there is one. 133$configFile = $ENV{"HOME"} . "/.colorcvsrc"; 134if (-f $configFile) 135{ 136 loadPreferences($configFile); 137} 138 139# Get the terminal type. 140$terminal = $ENV{"TERM"} || "dumb"; 141 142$commit = 0; 143foreach (@ARGV) 144{ 145 if(/^ci$/ || /^commit$/ || /^import$/ || /^prop/ || /^p[delsg]$/) 146 { 147 $commit = 1; 148 break; 149 } 150 elsif (! /^-/) 151 { 152 break; 153 } 154} 155 156# If it's in the list of terminal types not to color, or if 157# we're writing to something that's not a tty, don't do color. 158if (! -t STDOUT || $commit == 1 || $nocolor{$terminal}) 159{ 160 exec $svnCmd, @ARGV; 161 die("Couldn't exec"); 162} 163 164sub svn_not_found() { 165 die ("$svnCmd not found, add svn=/full/path/to/svn to ~/.colorcvsrc"); 166} 167 168# Check if we have SVN binary accessible. Of course, there could 169# be a race, but we don't care - all we want is to print out 170# nice error if executable SVN binary could not be found. 171if (file_name_is_absolute($svnCmd)) { 172 svn_not_found unless -f $svnCmd and -x $svnCmd; 173} else { 174 my $found = 0; 175 foreach (path()) { 176 my $path = catfile($_, $svnCmd); 177 if (-f $path and -x $path) { 178 $found = 1; 179 last; 180 } 181 } 182 svn_not_found unless $found; 183} 184 185# Keep the pid of the svn process so we can get its return 186# code and use that as our return code. 187$svn_pid = open3('<&STDIN', \*SVNOUT, \*SVNOUT, $svnCmd, @ARGV); 188$svnName = $svnCmd; 189$svnName =~ s,.*/(.*)$,\1,; 190 191# Colorize the output from the svn program. 192while(<SVNOUT>) 193{ 194 chomp; 195 if (m/^ (.).+/) # Property changed only 196 { 197 print($propcolors{$1}, $_, color("reset")); 198 } 199 elsif (m/^(.).+/) # S filename 200 { 201 print($colors{$1}, $_, color("reset")); 202 } 203 elsif (m/warning:/) # warning 204 { 205 print($colors{"warning"}, $_, color("reset")); 206 } 207 elsif (m/^$svnName[^:]*: / || m/^svn server: /) # server message 208 { 209 print($colors{"server"}, $_, color("reset")); 210 } 211 else # Anything else 212 { 213 # Print normally. 214 print(color("reset"), $_); 215 } 216 print "\n"; 217} 218 219# Get the return code of the svn program and exit with that. 220waitpid($svn_pid, 0); 221exit ($? >> 8); 222