Follow-up to r29036: Now that the "mergeinfo" transaction file is no
[svn.git] / contrib / cgi / tweak-log.cgi
blobcb680bc6f4d4d93dada85356e8862cb85e3be2e5
1 #!/usr/bin/perl
2 ###############################################################################
3 # Tweak Subversion log messages
4 # -----------------------------
5 #
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,
15 # which will:
17 # - Display the current log message as static text.
18 # - Present a textarea for editing, initialized with the current
19 # log message.
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 ###############################################################################
40 use strict;
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( );
57 &main( );
60 #-----------------------------------------------------------------------------#
61 sub html_escape
62 # (log)
63 #-----------------------------------------------------------------------------#
65 my $str = shift;
66 $str =~ s/&/&/g;
67 $str =~ s/>/>/g;
68 $str =~ s/</&lt;/g;
69 return $str;
73 #-----------------------------------------------------------------------------#
74 sub doCGI
75 # (void)
76 #-----------------------------------------------------------------------------#
78 my $lCGI = new CGI;
79 my @lFields = $lCGI->param;
80 my $lField;
81 my %lCGIData = ();
83 foreach $lField ( @lFields )
85 $lCGIData{ uc $lField } = $lCGI->param( $lField );
87 return( %lCGIData );
91 #-----------------------------------------------------------------------------#
92 sub doError
93 # (error)
94 #-----------------------------------------------------------------------------#
96 my $error = shift @_;
98 print "<html><head><title>Tweak Log - Error</title></head>\n";
99 print "<body><h1>ERROR</h1>\n<p>$error</p></body></html>\n";
100 return;
104 #-----------------------------------------------------------------------------#
105 sub main
106 # (void)
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 )
115 &doFetchLog();
117 elsif( $gCGIValues{'ACTION'} =~ /commit/i )
119 &doCommitLog();
121 else
123 &doInitialForm();
125 return;
129 #-----------------------------------------------------------------------------#
130 sub doInitialForm
131 # (void)
132 #-----------------------------------------------------------------------------#
134 my $youngest = `$gSvnlookCmd youngest $gReposPath`;
135 my $rev;
136 my $oldest;
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";
141 print "<p>\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";
146 print "<p>\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";
149 print "</p>\n";
150 chomp $youngest;
151 $oldest = $youngest - $gNumRecentCommits + 1;
152 $oldest = 1 if( $oldest < 1 );
153 $rev = $youngest;
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;
161 print "<hr />\n";
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";
166 map {
167 $_ = &html_escape ($_);
168 } @infolines;
169 print @infolines;
170 print "</pre><br />\n";
171 print "<a href=\"#__top__\">(back to top)</a>\n";
172 $rev--;
174 print "</body></html>\n";
175 return;
179 #-----------------------------------------------------------------------------#
180 sub isValidRev
181 # (rev)
182 #-----------------------------------------------------------------------------#
184 my $youngest = `$gSvnlookCmd youngest $gReposPath`;
185 my $rev = shift @_;
187 if(not (( $youngest =~ /^\d+$/) and
188 ( $youngest > 0 )))
190 &doError( "Unable to determine youngest revision" );
191 return 0;
193 if(not (( $rev =~ /^\d+$/) and
194 ( $rev <= $youngest )))
196 &doError( "'$rev' is not a valid revision number" );
197 return 0;
199 return 1;
203 #-----------------------------------------------------------------------------#
204 sub doFetchLog
205 # (void)
206 #-----------------------------------------------------------------------------#
208 my $rev = $gCGIValues{'REV'};
209 my $log;
210 my $escaped_log; ## HTML-escaped version of $log
212 # Make sure we've requested a valid revision.
213 if( not &isValidRev( $rev ))
215 return;
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";
225 print "<body>\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";
238 print $escaped_log;
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";
244 return;
248 #-----------------------------------------------------------------------------#
249 sub doCommitLog
250 # (void)
251 #-----------------------------------------------------------------------------#
253 my $rev = $gCGIValues{'REV'};
254 my $log = $gCGIValues{'LOG'};
255 my $orig_log;
256 my $tempfile = "$gTempfilePrefix.$$";
258 # Make sure we are about to change a valid revision.
259 if (not &isValidRev( $rev ))
261 return;
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.");
272 return;
275 # Open a tempfile
276 if (not (open( LOGFILE, "> $tempfile")))
278 &doError ("Unable to open temporary file.");
279 return;
282 # Dump the new log into the tempfile (and close it)
283 print LOGFILE $log;
284 close LOGFILE;
286 # Tell our history file what we're about to do.
287 if ($gHistoryFile)
289 if (not (open (HISTORY, ">> $gHistoryFile")))
291 &doError ("Unable to open history file.");
292 return;
294 print HISTORY "====================================================\n";
295 print HISTORY "REVISION $rev WAS:\n";
296 print HISTORY "----------------------------------------------------\n";
297 print HISTORY $orig_log;
298 print HISTORY "\n";
301 # Now, make the mods
302 if ($gBypassRevpropHooks)
304 `$gSvnadminCmd setlog $gReposPath -r$rev $tempfile --bypass-hooks`;
306 else
308 `$gSvnadminCmd setlog $gReposPath -r$rev $tempfile`;
311 # ...and remove the tempfile. It is, after all, temporary.
312 unlink $tempfile;
314 # Now, tell the history file what we did.
315 if ($gHistoryFile)
317 print HISTORY "----------------------------------------------------\n";
318 print HISTORY "REVISION $rev IS:\n";
319 print HISTORY "----------------------------------------------------\n";
320 print HISTORY $log;
321 print HISTORY "\n";
322 close HISTORY;
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";
330 print "<body>\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";
335 return;