2 ###############################################################################
3 # Tweak Subversion log messages
4 # -----------------------------
6 # It sure would be nice to be able to change the log messages on
7 # committed revisions of the Subversion repository via the web. This
8 # is a quick attempt at making that happen.
10 # The idea here is that you visit this script at the web page. With
11 # no action supplied, it will present a form asking for the revision
12 # of the log you wish to change.
14 # Upon submitting the form, it will come back with yet another form,
17 # - Display the current log message as static text.
18 # - Present a textarea for editing, initialized with the current
21 # The user can edit the message in the textarea, then submit that form,
22 # which will return a confirmation and show the new log message.
24 # ====================================================================
25 # Copyright (c) 2001-2003 CollabNet. All rights reserved.
27 # This software is licensed as described in the file COPYING, which
28 # you should have received as part of this distribution. The terms
29 # are also available at http://subversion.tigris.org/license.html.
30 # If newer versions of this license are posted there, you may use a
31 # newer version instead, at your option.
33 # This software consists of voluntary contributions made by many
34 # individuals. For exact contribution history, see the revision
35 # history and logs, available at http://subversion.tigris.org/.
36 # ====================================================================
38 ###############################################################################
41 use CGI
qw(:standard);
43 ###############################################################################
44 # Configuration Section
46 my $gSvnlookCmd = '/usr/local/bin/svnlook';
47 my $gSvnadminCmd = '/usr/local/bin/svnadmin';
48 my $gReposPath = '/usr/www/repositories/svn';
49 my $gActionURL = './tweak-log.cgi';
50 my $gTempfilePrefix = '/tmp/tweak-cgi';
51 my $gHistoryFile = './TWEAKLOG';
52 my $gBypassRevpropHooks = 0; # set to 1 to bypass the repository hook system
53 my $gNumRecentCommits = 20; # number of recent commits to show on init form
54 ###############################################################################
56 my %gCGIValues = &doCGI
( );
60 #-----------------------------------------------------------------------------#
63 #-----------------------------------------------------------------------------#
73 #-----------------------------------------------------------------------------#
76 #-----------------------------------------------------------------------------#
79 my @lFields = $lCGI->param;
83 foreach $lField ( @lFields )
85 $lCGIData{ uc $lField } = $lCGI->param( $lField );
91 #-----------------------------------------------------------------------------#
94 #-----------------------------------------------------------------------------#
98 print "<html><head><title>Tweak Log - Error</title></head>\n";
99 print "<body><h1>ERROR</h1>\n<p>$error</p></body></html>\n";
104 #-----------------------------------------------------------------------------#
107 #-----------------------------------------------------------------------------#
109 # Print out HTTP headers.
110 print "Content-type: text/html; charset=UTF-8\n\n";
112 # Figure out what action to take.
113 if( $gCGIValues{'ACTION'} =~ /fetch/i )
117 elsif( $gCGIValues{'ACTION'} =~ /commit/i )
129 #-----------------------------------------------------------------------------#
132 #-----------------------------------------------------------------------------#
134 my $youngest = `$gSvnlookCmd youngest $gReposPath`;
138 print "<html>\n<head>\n<title>Tweak Log</title>\n</head>\n";
139 print "<body>\n<form action=\"$gActionURL\" method=\"post\">\n";
140 print "<a name=\"__top__\"></a>\n";
142 print "Boy, I sure would like to modify that log message for \n";
143 print "revision <input type=\"text\" name=\"rev\" value\"\">\n";
144 print "<input type=\"submit\" name=\"action\" value=\"Fetch Log\">\n";
145 print "</p></form>\n";
147 print "For convenience, here are the most recent $gNumRecentCommits\n";
148 print "commits (click the revision number to edit that revision's log):\n";
151 $oldest = $youngest - $gNumRecentCommits + 1;
152 $oldest = 1 if( $oldest < 1 );
154 while( $rev >= $oldest )
156 my @infolines = `$gSvnlookCmd info $gReposPath -r $rev`;
157 my $author = shift @infolines;
158 my $date = shift @infolines;
159 my $log_size = shift @infolines;
162 print "<a href=\"$gActionURL?action=Fetch+Log&rev=$rev\">Revision $rev</a>:<br />\n";
163 print "<i>Author: $author</i><br />\n";
164 print "<i>Date: $date</i><br />\n";
165 print "<i>Log: </i><br /><pre>\n";
167 $_ = &html_escape
($_);
170 print "</pre><br />\n";
171 print "<a href=\"#__top__\">(back to top)</a>\n";
174 print "</body></html>\n";
179 #-----------------------------------------------------------------------------#
182 #-----------------------------------------------------------------------------#
184 my $youngest = `$gSvnlookCmd youngest $gReposPath`;
187 if(not (( $youngest =~ /^\d+$/) and
190 &doError
( "Unable to determine youngest revision" );
193 if(not (( $rev =~ /^\d+$/) and
194 ( $rev <= $youngest )))
196 &doError
( "'$rev' is not a valid revision number" );
203 #-----------------------------------------------------------------------------#
206 #-----------------------------------------------------------------------------#
208 my $rev = $gCGIValues{'REV'};
210 my $escaped_log; ## HTML-escaped version of $log
212 # Make sure we've requested a valid revision.
213 if( not &isValidRev
( $rev ))
218 # Fetch the log for that revision.
219 $log = `$gSvnlookCmd log $gReposPath -r $rev`;
221 $escaped_log = &html_escape
($log);
223 # Display the form for editing the revision
224 print "<html>\n<head>\n<title>Tweak Log - Log Edit</title>\n</head>\n";
226 print "<h1>Editing Log Message for Revision $rev</h1>\n";
227 print "<h2>Current log message:</h2>\n";
228 print "<blockquote><hr /><pre>$escaped_log</pre><hr /></blockquote>\n";
229 print "<p><font color=\"red\">\n";
230 print "<i>Every change made is logged in <tt>${gHistoryFile}</tt>.\n";
231 print "If you make a bogus\n";
232 print "change, you can still recover the old message from there.</i>\n";
233 print "</font></p>\n";
234 print "<form action=\"$gActionURL\" method=\"post\">\n";
235 print "<h2>New log message:</h2>\n";
236 print "<blockquote>\n";
237 print "<textarea cols=\"80\" rows=\"25\" wrap=\"off\" name=\"log\">\n";
239 print "</textarea><br />\n";
240 print "<input type=\"hidden\" name=\"rev\" value=\"$rev\">\n";
241 print "<input type=\"submit\" name=\"action\" value=\"Commit Changes\">\n";
242 print "</blockquote>\n";
243 print "</form></body></html>\n";
248 #-----------------------------------------------------------------------------#
251 #-----------------------------------------------------------------------------#
253 my $rev = $gCGIValues{'REV'};
254 my $log = $gCGIValues{'LOG'};
256 my $tempfile = "$gTempfilePrefix.$$";
258 # Make sure we are about to change a valid revision.
259 if (not &isValidRev
( $rev ))
264 # Get the original log from the repository.
265 $orig_log = `$gSvnlookCmd log $gReposPath -r $rev`;
267 # If nothing was changed, go complain to the user (shame on him for
268 # wasting our time like that!)
269 if ($log eq $orig_log)
271 &doError
("Log message doesn't appear to have been edited.");
276 if (not (open( LOGFILE
, "> $tempfile")))
278 &doError
("Unable to open temporary file.");
282 # Dump the new log into the tempfile (and close it)
286 # Tell our history file what we're about to do.
289 if (not (open (HISTORY
, ">> $gHistoryFile")))
291 &doError
("Unable to open history file.");
294 print HISTORY
"====================================================\n";
295 print HISTORY
"REVISION $rev WAS:\n";
296 print HISTORY
"----------------------------------------------------\n";
297 print HISTORY
$orig_log;
302 if ($gBypassRevpropHooks)
304 `$gSvnadminCmd setlog $gReposPath -r$rev $tempfile --bypass-hooks`;
308 `$gSvnadminCmd setlog $gReposPath -r$rev $tempfile`;
311 # ...and remove the tempfile. It is, after all, temporary.
314 # Now, tell the history file what we did.
317 print HISTORY
"----------------------------------------------------\n";
318 print HISTORY
"REVISION $rev IS:\n";
319 print HISTORY
"----------------------------------------------------\n";
325 # Now, re-read that logfile
326 $log = `$gSvnlookCmd log $gReposPath -r $rev`;
327 $log = &html_escape
($log);
329 print "<html>\n<head>\n<title>Tweak Log - Log Changed</title>\n</head>\n";
331 print "<h1>Success!</h1>\n";
332 print "<h2>New Log Message for Revision $rev</h2>\n";
333 print "<blockquote><hr /><pre>$log</pre><hr /></blockquote>\n";
334 print "</body></html>\n";