Bonsai and Tinderbox have been freed.
This commit is contained in:
Родитель
1394aed0fa
Коммит
a5ab99df60
|
@ -0,0 +1,22 @@
|
|||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
CFLAGS = -g
|
||||
|
||||
trapdoor: trapdoor.o
|
||||
cc -o trapdoor trapdoor.o
|
|
@ -0,0 +1,460 @@
|
|||
This is Bonsai. See <http://www.mozilla.org/bonsai.html>.
|
||||
|
||||
|
||||
=================================
|
||||
What's What in the Bonsai sources:
|
||||
=================================
|
||||
|
||||
|
||||
CGI.tcl ???
|
||||
|
||||
Makefile: builds the "trapdoor" program
|
||||
|
||||
SourceChecker.cgi scc wrote to help sanitize code. DELETE
|
||||
Called by: nobody
|
||||
|
||||
SourceChecker.pm ???
|
||||
|
||||
addcheckin.tcl ???
|
||||
|
||||
admin.cgi TCL. Select from various administrative tasks
|
||||
(which require a password.)
|
||||
|
||||
Called by: toplevel.cgi
|
||||
|
||||
Calls:
|
||||
doadmin.cgi password=<text> treeid=<text>
|
||||
command=[open|close]
|
||||
closetimestamp=<time-text>
|
||||
lastgood=<time-text>
|
||||
doclear=<checkbox>
|
||||
|
||||
doadmin.cgi password=<text> treeid=<text>
|
||||
command=tweaktimes
|
||||
lastgood=<time-text>
|
||||
lastclose=<time-text>
|
||||
|
||||
doadmin.cgi password=<text> treeid=<text>
|
||||
command=editmotd
|
||||
origmotd=<text>
|
||||
motd=<text>
|
||||
|
||||
editmessage.cgi treeid=<text>
|
||||
msgname=[openmessage|closemessage|
|
||||
treeopened|treeopenedsamehook|
|
||||
treeclosed]
|
||||
#### note: no password?
|
||||
|
||||
repophook.cgi password=<text> treeid=<text>
|
||||
command=repophook
|
||||
startfrom=<time-text>
|
||||
|
||||
rebuildtaginfo.cgi password=<text>
|
||||
treeid=<text>
|
||||
command=rebuildtaginfo
|
||||
|
||||
rebuildcvshistory.cgi password=<text>
|
||||
treeid=<text>
|
||||
command=rebuildcvs
|
||||
startfrom=<time-text>
|
||||
firstfile=<time-text>
|
||||
subdir=<time-text>
|
||||
|
||||
doadmin.cgi password=<text> treeid=<text>
|
||||
command=changepassword
|
||||
password=<text>
|
||||
newpassword=<text>
|
||||
newpassword2=<text>
|
||||
doglobal=<radio>
|
||||
|
||||
adminfuncs.tcl ???
|
||||
|
||||
adminmail.tcl ???
|
||||
|
||||
bonsai.gif uh, a corrupted gif file.
|
||||
|
||||
branchspam.cgi failed attempt to web-afy branch spam too DELETE
|
||||
Called by: nobody
|
||||
Calls: branchspammer.cgi
|
||||
|
||||
branchspammer.cgi more garbage
|
||||
Called by: branchspam.cgi
|
||||
Calls: nobody
|
||||
|
||||
changebar.tcl ???
|
||||
|
||||
closemessage ???
|
||||
|
||||
configure/ ???
|
||||
|
||||
contacthelp.html ???
|
||||
|
||||
countcheckins.cgi TCL. Draws a graph of checkins for the various
|
||||
Bonsai 'hooks'.
|
||||
Called by: toplevel.cgi
|
||||
Calls: nobody
|
||||
|
||||
createlegaldirs.tcl ???
|
||||
|
||||
crontab ???
|
||||
|
||||
cvsblame.cgi Runs through a CVS file and tells you who changed what.
|
||||
Calls:
|
||||
rview.cgi dir= cvsroot= rev=
|
||||
cvsblame.cgi file= rev= root= mark=
|
||||
cvsblame.cgi set_line= (cookie magic?)
|
||||
cvsblame.cgi root= file= rev= use_html=
|
||||
Called by:
|
||||
cvsguess.cgi
|
||||
moduleanalyse.cgi
|
||||
Used to be called by:
|
||||
cvslog.cgi
|
||||
|
||||
cvsblame.pl ???
|
||||
|
||||
cvsguess.cgi Given a file name, try to figure out what directory
|
||||
it's in. then link to cvsblame.cgi. parameters are
|
||||
the same.
|
||||
|
||||
Seems to take an exact file name (sans directory),
|
||||
then do a redirect to cvsblame.cgi. If there are
|
||||
more than one file of that name, it presents a list.
|
||||
This is (I think) redundant with LXR's file name
|
||||
search.
|
||||
|
||||
Calls:
|
||||
cvsblame.cgi file= rev= mark= #
|
||||
Called by: nobody
|
||||
|
||||
cvsindex.pl ???
|
||||
|
||||
cvslog.cgi Web interface to "cvs log".
|
||||
Calls:
|
||||
rview.cgi dir= cvsroot= rev=
|
||||
cvslog.cgi file= root= rev=
|
||||
sort=[revision|date|author]
|
||||
author=
|
||||
cvsview2.cgi
|
||||
command=DIFF_FRAMESET
|
||||
diff_mode=context
|
||||
whitespace_mode=show
|
||||
root= subdir= file=
|
||||
rev1= rev2=
|
||||
cvsview2.cgi
|
||||
command=DIRECTORY
|
||||
subdir= files= root= branch=
|
||||
|
||||
Used to call:
|
||||
cvsblame.cgi file= rev= root=
|
||||
|
||||
cvsmenu.pl ???
|
||||
|
||||
cvsquery.cgi Displays the results of a query entered in cvsqueryform
|
||||
Called by:
|
||||
cvsqueryform.cgi
|
||||
Calls:
|
||||
cvsqueryform.cgi
|
||||
cvsview2 command=DIRECTORY
|
||||
subdir= files= branch= root=
|
||||
cvsview2.cgi command=DIFF_FRAMESET
|
||||
diff_mode=context
|
||||
whitespace_mode=show
|
||||
subdir= file= rev1= rev2= root=
|
||||
multidiff.cgi name=allchanges cvsroot=
|
||||
cvsquery.cgi sortby=
|
||||
../registry/who.cgi email=
|
||||
http://scopus.mcom.com/bugsplat/show_bug.cgi
|
||||
|
||||
cvsquery.pl ???
|
||||
|
||||
cvsqueryform.cgi Main screen to let you query the CVS database.
|
||||
Called by:
|
||||
cvsblame.cgi
|
||||
cvslog.cgi
|
||||
cvsquery.cgi
|
||||
toplevel.cgi
|
||||
Calls:
|
||||
cvsregexp.html
|
||||
cvsquery.cgi
|
||||
module=[all|allrepositories|?]
|
||||
branch=
|
||||
branchtype=[match|regexp]
|
||||
directory=<text>
|
||||
file=<text>
|
||||
who=<text>
|
||||
whotype=[match|regexp]
|
||||
sortby=[Date|Who|File|Change Size]
|
||||
date=[hours|day|week|month|all|
|
||||
explicit]
|
||||
hours=
|
||||
mindate=
|
||||
maxdate=
|
||||
cvsroot=
|
||||
|
||||
cvsregexp.html ???
|
||||
|
||||
cvsview2.cgi Lets you view CVS diffs.
|
||||
Called by:
|
||||
cvsblame.cgi
|
||||
cvslog.cgi
|
||||
cvsquery.cgi
|
||||
show2.cgi
|
||||
showcheckins.cgi
|
||||
Calls:
|
||||
rview.cgi dir= cvsroot= rev=
|
||||
cvsview2.cgi subdir= command=DIFF
|
||||
root= file= rev1= rev2=
|
||||
cvsview2.cgi subdir= command=DIFF_LINKS
|
||||
root= file= rev1= rev2=
|
||||
cvsview2.cgi subdir= command=DIFF
|
||||
root= file= rev1= rev2= #
|
||||
cvsview2.cgi subdir= command=DIFF_FRAMESET
|
||||
root= file= rev1= rev2=
|
||||
cvsview2.cgi subdir= command=DIRECTORY
|
||||
root= files= branch= skip=
|
||||
cvsview2.cgi subdir= command=LOG
|
||||
root= file= rev=
|
||||
|
||||
doadmin.cgi TCL. Executes admin things asked for in admin.cgi
|
||||
Called by:
|
||||
admin.cgi
|
||||
Calls:
|
||||
mailto:clienteng
|
||||
|
||||
doeditcheckin.cgi TCL. Edits a checkin on the hook.
|
||||
Called by:
|
||||
editcheckin.cgi
|
||||
Calls:
|
||||
nobody
|
||||
|
||||
doeditmessage.cgi TCL. Edits one of the email messages that bonsai sends
|
||||
people.
|
||||
Called by:
|
||||
editmessage.cgi
|
||||
Calls:
|
||||
nobody
|
||||
|
||||
doeditprofile.cgi TCL. Edit peoples contact info. Left-over code from
|
||||
before we started getting this info from LDAP.
|
||||
Called by:
|
||||
editprofile.cgi
|
||||
Calls:
|
||||
nobody
|
||||
|
||||
doeditwhiteboard.cgi TCL. Edits the free-for-all whiteboard.
|
||||
Called by:
|
||||
editwhiteboard.cgi
|
||||
Calls:
|
||||
nobody
|
||||
|
||||
dolog.pl ???
|
||||
|
||||
dotweak.cgi TCL. Tweaks a bunch of checkins in ahook at once.
|
||||
Called by:
|
||||
show2.cgi
|
||||
showcheckins.cgi
|
||||
Calls:
|
||||
nobody
|
||||
|
||||
editcheckin.cgi TCL. Edits a checkin on the hook.
|
||||
Called by:
|
||||
show2.cgi
|
||||
showcheckins.cgi
|
||||
Calls:
|
||||
doeditcheckin.cgi
|
||||
|
||||
editmessage.cgi TCL. Edits one of the email messages that bonsai sends
|
||||
people.
|
||||
Called by:
|
||||
admin.cgi
|
||||
Calls:
|
||||
doeditmessage.cgi
|
||||
|
||||
editprofile.cgi TCL. Edit peoples contact info. Left-over code from
|
||||
before we started getting this info from LDAP.
|
||||
Called by:
|
||||
localprofile.cgi
|
||||
Calls:
|
||||
doeditprofile.cgi
|
||||
|
||||
editwhiteboard.cgi TCL. Edits the free-for-all whiteboard.
|
||||
Called by:
|
||||
toplevel.cgi
|
||||
Calls:
|
||||
doeditwhiteboard.cgi
|
||||
|
||||
globals.tcl ???
|
||||
|
||||
handleAdminMail.tcl ???
|
||||
|
||||
handleCheckinMail.tcl ???
|
||||
|
||||
header.pl ???
|
||||
|
||||
index.html ???
|
||||
|
||||
indextest.pl ???
|
||||
|
||||
lloydcgi.pl parses CGI args from $QUERY_STRING and leaves them
|
||||
in $form{$key}; and puts cookies in %cookie_jar.
|
||||
Calls: nobody
|
||||
Called by: everybody
|
||||
|
||||
localprofile.cgi TCL. Display peoples contact info. Left-over code
|
||||
from before we started getting this info from LDAP.
|
||||
Called by:
|
||||
nobody
|
||||
Calls:
|
||||
editprofile.cgi
|
||||
profile.cgi
|
||||
|
||||
maketables.sh ???
|
||||
Unused?
|
||||
|
||||
moduleanalyse.cgi Shows the directories in a module.
|
||||
Called by:
|
||||
nobody
|
||||
Calls:
|
||||
moduleanalyse.cgi module=[all|?] cvsroot=
|
||||
rview.cgi dir= cvsroot=
|
||||
cvsblame.cgi file= root=
|
||||
|
||||
modules.pl ???
|
||||
Called by:
|
||||
branchspam.cgi
|
||||
cvsqueryform.cgi
|
||||
moduleanalyse.cgi
|
||||
|
||||
multidiff.cgi Implements the "Show me ALL the Diffs" button
|
||||
Called by:
|
||||
cvsquery.cgi
|
||||
show2.cgi
|
||||
showcheckins.cgi
|
||||
Calls:
|
||||
nobody
|
||||
|
||||
myglobrecur.tcl ???
|
||||
|
||||
openmessage ???
|
||||
|
||||
perlifyconfig.tcl ???
|
||||
|
||||
processqueue.pl ???
|
||||
|
||||
profile.cgi TCL. Stupid interface to LDAP to show all the info
|
||||
about a person.
|
||||
Called by:
|
||||
localprofile.cgi
|
||||
show2.cgi
|
||||
Calls:
|
||||
profile.cgi person=
|
||||
|
||||
rebuildcvshistory.cgi TCL. Admin script to go rebuild the bonsai database
|
||||
from CVS.
|
||||
Called by:
|
||||
admin.cgi
|
||||
Calls:
|
||||
nobody
|
||||
|
||||
rebuilddatabase.tcl ???
|
||||
|
||||
rebuildtaginfo.cgi TCL. Half-written piece of junk to try and remember
|
||||
things about tags. Should probably nuke it.
|
||||
Called by:
|
||||
admin.cgi
|
||||
|
||||
repophook.cgi TCL. Rebuilds a bonsai hook from the bonsai database.
|
||||
Called by:
|
||||
admin.cgi
|
||||
Calls:
|
||||
nobody
|
||||
|
||||
reposfiles.pl ???
|
||||
|
||||
rview.cgi Lets you browse a directory in a CVS repository.
|
||||
Called by:
|
||||
cvsblame.cgi
|
||||
cvslog.cgi
|
||||
cvsview2.cgi
|
||||
moduleanalyse.cgi
|
||||
Calls:
|
||||
rview.cgi dir= cvsroot= rev=
|
||||
rview.cgi dir= cvsroot= rev= ?=chdir
|
||||
rview.cgi dir= cvsroot= rev= ?=Set Branch
|
||||
&make_cgi_args ???
|
||||
../registry/file.cgi cvsroot= file= dir=
|
||||
|
||||
show2.cgi TCL. This seems to be a variant on showcheckins.cgi?
|
||||
Called by:
|
||||
nobody
|
||||
Calls:
|
||||
dotweak.cgi
|
||||
showcheckins.cgi [various funky args]
|
||||
editcheckin.cgi id= [various funky args]w
|
||||
profile.cgi person= [various funky args]
|
||||
cvsview2.cgi subdir= files= command=DIRECTORY
|
||||
branch=
|
||||
http://w3/cgi/cvsview2.cgi subdir= files=
|
||||
command=DIRECTORY
|
||||
multidiff.cgi allchanges=
|
||||
|
||||
showcheckins.cgi TCL. Shows some set of checkins in a bonsai hook.
|
||||
Called by:
|
||||
admin.cgi
|
||||
show2.cgi
|
||||
toplevel.cgi
|
||||
Calls:
|
||||
dotweak.cgi
|
||||
showcheckins.cgi [various funky args]
|
||||
editcheckin.cgi id= [various funky args]w
|
||||
http://phonebook/ds/dosearch/phonebook/...
|
||||
cvsview2.cgi root= subdir= files=
|
||||
command=DIRECTORY branch=
|
||||
http://w3/cgi/cvsview2.cgi subdir= files=
|
||||
command=DIRECTORY
|
||||
multidiff.cgi allchanges=
|
||||
|
||||
status/ ???
|
||||
|
||||
switchtree.cgi TCL. Lets you choose a different bonsai branch.
|
||||
Called by:
|
||||
toplevel.cgi
|
||||
Calls:
|
||||
nobody
|
||||
|
||||
testlock.pl ???
|
||||
|
||||
toplevel.cgi TCL. Main interface to the bonsai hook.
|
||||
Called by:
|
||||
CGI.tcl
|
||||
contacthelp.html
|
||||
index.html
|
||||
sheriff2.html
|
||||
switchtree.cgi
|
||||
toplevel.cgi
|
||||
viewold.cgi
|
||||
Calls:
|
||||
editwhiteboard.cgi [...]
|
||||
http://phonebook/ds/dosearch/phonebook/...
|
||||
showcheckins.cgi
|
||||
http://warp/tinderbox/showbuilds.cgi
|
||||
switchtree.cgi [...]
|
||||
news:mcom.dev.client.build.busted
|
||||
http://phonebook/
|
||||
viewold.cgi [...]
|
||||
countcheckins.cgi [...]
|
||||
admin.cgi [...]
|
||||
index.html
|
||||
http://warp/client/dogbert/tree.html
|
||||
contacthelp.html
|
||||
http://warp/client/dogbert/buildlore/index.html
|
||||
|
||||
trapdoor.c ???
|
||||
|
||||
utils.pl ???
|
||||
|
||||
viewold.cgi TCL. Lets you choose an old bonsai hook to view.
|
||||
Called by:
|
||||
toplevel.cgi
|
||||
Calls:
|
||||
toplevel.cgi treeid=
|
|
@ -0,0 +1,237 @@
|
|||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
# SourceChecker.cgi -- tools for creating or modifying the dictionary
|
||||
# used by cvsblame.cgi.
|
||||
#
|
||||
# Created: Scott Collins <scc@netscape.com>, 4 Feb 1998.
|
||||
#
|
||||
# Arguments (passes via GET or POST):
|
||||
# ...
|
||||
#
|
||||
|
||||
use CGI;
|
||||
use SourceChecker;
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Global
|
||||
#
|
||||
|
||||
$query = new CGI;
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Subroutines
|
||||
#
|
||||
|
||||
|
||||
sub print_page_header()
|
||||
{
|
||||
print <<'END_OF_HEADER';
|
||||
<H1>SourceChecker Dictionary Maintainance</H1>
|
||||
END_OF_HEADER
|
||||
}
|
||||
|
||||
|
||||
sub print_page_trailer()
|
||||
{
|
||||
print <<'END_OF_TRAILER';
|
||||
<HR>
|
||||
<FONT SIZE=-1>
|
||||
Last updated 5 Feb 1998.
|
||||
<A HREF="SourceChecker.cgi">Dictionary maintainance and help</A>.</FONT>
|
||||
Mail feedback to <A HREF="mailto:scc?subject=[SourceChecker.cgi]"><scc@netscape.com></A>.
|
||||
END_OF_TRAILER
|
||||
}
|
||||
|
||||
|
||||
|
||||
$error_header = '<HR><H2>I couldn\'t process your request...</H2>';
|
||||
|
||||
sub print_error($)
|
||||
{
|
||||
local $message = shift;
|
||||
print "$error_header<P><EM>Error</EM>: $message</P>";
|
||||
$error_header = '';
|
||||
}
|
||||
|
||||
|
||||
sub print_query_building_form()
|
||||
{
|
||||
print $query->start_multipart_form;
|
||||
|
||||
print '<HR><H2>Build a new request</H2>';
|
||||
print '<P>...to modify or create a remote dictionary with words from one or more local files.</P>';
|
||||
|
||||
print '<H3>Files on the server</H3>';
|
||||
print '<P>...i.e., the dictionary to be created or modified.</P>';
|
||||
|
||||
print $query->textfield( -name=>'dictionary',
|
||||
-default=>'',
|
||||
-override=>1,
|
||||
-size=>30 );
|
||||
print '-- the path to dictionary.';
|
||||
|
||||
print '<H3>Files on your local machine</H3>';
|
||||
print '<P>...that will be uploaded to the server, so their contents can be added to the dictionary.</P>';
|
||||
|
||||
print '<BR>';
|
||||
print $query->filefield( -name=>'ignore_english', -size=>30 );
|
||||
print '-- contains english (i.e., transformable) words to ignore.';
|
||||
|
||||
print '<BR>';
|
||||
print $query->filefield( -name=>'ignore_strings', -size=>30 );
|
||||
print '-- contains identifiers (i.e., non-transformable) words to ignore.';
|
||||
|
||||
print '<BR>';
|
||||
print $query->filefield( -name=>'flag_strings', -size=>30 );
|
||||
print '-- contains identifiers words to be flagged.';
|
||||
|
||||
print '<BR>';
|
||||
print $query->filefield( -name=>'ignore_names', -size=>30 );
|
||||
print '-- contains user names to be ignored.';
|
||||
|
||||
print '<BR>';
|
||||
print $query->submit;
|
||||
|
||||
print $query->endform;
|
||||
}
|
||||
|
||||
|
||||
sub do_add_good_words($)
|
||||
{
|
||||
local $file = shift;
|
||||
|
||||
while ( <$file> )
|
||||
{
|
||||
next if /\#/;
|
||||
add_good_words($_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub do_add_bad_words($)
|
||||
{
|
||||
local $file = shift;
|
||||
|
||||
while ( <$file> )
|
||||
{
|
||||
next if /\#/;
|
||||
add_bad_words($_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub do_add_good_english($)
|
||||
{
|
||||
local $file = shift;
|
||||
|
||||
while ( <$file> )
|
||||
{
|
||||
next if /\#/;
|
||||
add_good_english($_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub do_add_names($)
|
||||
{
|
||||
local $file = shift;
|
||||
|
||||
while ( <$file> )
|
||||
{
|
||||
next if /\#/;
|
||||
add_names($_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub handle_query()
|
||||
{
|
||||
$dictionary_path = $query->param('dictionary');
|
||||
if ( ! $dictionary_path )
|
||||
{
|
||||
print_error('You didn\'t supply a path to the dictionary file.');
|
||||
return;
|
||||
}
|
||||
|
||||
dbmopen %SourceChecker::token_dictionary, "$dictionary_path", 0666
|
||||
|| print_error("The dictionary you named could not be opened.");
|
||||
|
||||
$added_some_words = 0;
|
||||
|
||||
if ( $file_of_good_english = $query->param('ignore_english') )
|
||||
{
|
||||
do_add_good_english($file_of_good_english);
|
||||
$added_some_words = 1;
|
||||
}
|
||||
|
||||
if ( $file_of_good_words = $query->param('ignore_strings') )
|
||||
{
|
||||
do_add_good_words($file_of_good_words);
|
||||
$added_some_words = 1;
|
||||
}
|
||||
|
||||
if ( $file_of_bad_words = $query->param('flag_strings') )
|
||||
{
|
||||
do_add_bad_words($file_of_bad_words);
|
||||
$added_some_words = 1;
|
||||
}
|
||||
|
||||
if ( $file_of_names = $query->param('ignore_names') )
|
||||
{
|
||||
do_add_names($file_of_names);
|
||||
$added_some_words = 1;
|
||||
}
|
||||
|
||||
if ( ! $added_some_words )
|
||||
{
|
||||
print_error("You did not supply any words to add to the dictionary.");
|
||||
}
|
||||
|
||||
dbmclose %SourceChecker::token_dictionary;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#
|
||||
# The main script
|
||||
#
|
||||
|
||||
print $query->header;
|
||||
print $query->start_html(-title=>'SourceChecker Dictionary Maintainance',
|
||||
-author=>'scc@netscape.com');
|
||||
|
||||
print_page_header();
|
||||
|
||||
if ( $query->param )
|
||||
{
|
||||
handle_query();
|
||||
}
|
||||
|
||||
print_query_building_form();
|
||||
print_page_trailer();
|
||||
|
||||
print $query->end_html;
|
||||
|
||||
__DATA__
|
||||
|
|
@ -0,0 +1,192 @@
|
|||
# -*- Mode: perl; tab-width: 4; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
package SourceChecker;
|
||||
require Exporter;
|
||||
@ISA = qw(Exporter);
|
||||
@EXPORT = qw(%token_dictionary, add_good_english, add_good_words, add_bad_words, add_names, tokenize_line, markup_line);
|
||||
@EXPORT_OK = qw($GOOD_TOKEN, $UNKNOWN_TOKEN, $BAD_TOKEN, $NAME_TOKEN, add_token, canonical_token, @markup_prefix, @markup_suffix);
|
||||
|
||||
$GOOD_TOKEN = \-1;
|
||||
$UNKNOWN_TOKEN = \0;
|
||||
$NAME_TOKEN = \1;
|
||||
$BAD_TOKEN = \2;
|
||||
|
||||
|
||||
@markup_prefix = ('<FONT COLOR="green">', '<FONT COLOR="red">', '<FONT COLOR="blue">');
|
||||
@markup_suffix = ('</FONT>', '</FONT>', '</FONT>');
|
||||
|
||||
|
||||
|
||||
sub canonical_token($)
|
||||
{
|
||||
my $token = shift;
|
||||
|
||||
if ( defined $token )
|
||||
{
|
||||
$token =~ s/[\'Õ\&]+//g;
|
||||
$token = length($token)>2 ? lc $token : undef;
|
||||
}
|
||||
|
||||
$token;
|
||||
}
|
||||
|
||||
|
||||
|
||||
sub _push_tokens($$)
|
||||
{
|
||||
# Note: inherits |@exploded_phrases| and |@exploded_tokens| from caller(s)
|
||||
push @exploded_phrases, shift;
|
||||
push @exploded_tokens, canonical_token(shift);
|
||||
}
|
||||
|
||||
|
||||
|
||||
sub _explode_line($)
|
||||
{
|
||||
# Note: inherits (and returns results into) |@exploded_phrases| and |@exploded_tokens| from caller(s)
|
||||
|
||||
my $line = shift;
|
||||
|
||||
my $between_tokens = 0;
|
||||
foreach $phrase ( split /([A-Za-z\'Õ\&]+)/, $line )
|
||||
{
|
||||
if ( $between_tokens = !$between_tokens )
|
||||
{
|
||||
_push_tokens($phrase, undef);
|
||||
next;
|
||||
}
|
||||
|
||||
for ( $_ = $phrase; $_; )
|
||||
{
|
||||
m/^[A-Z\'Õ\&]*[a-z\'Õ\&]*/;
|
||||
$token = $&;
|
||||
$_ = $';
|
||||
|
||||
if ( ($token =~ m/[A-Z][a-z\'Õ]+/) && $` )
|
||||
{
|
||||
$token = $&;
|
||||
_push_tokens($`, $`);
|
||||
}
|
||||
_push_tokens($token, $token);
|
||||
}
|
||||
}
|
||||
|
||||
$#exploded_phrases;
|
||||
}
|
||||
|
||||
|
||||
sub tokenize_line($)
|
||||
{
|
||||
my $line = shift;
|
||||
local @exploded_tokens;
|
||||
_explode_line($line);
|
||||
|
||||
my $i = -1;
|
||||
foreach $token ( @exploded_tokens )
|
||||
{
|
||||
$exploded_tokens[++$i] = $token if defined $token;
|
||||
}
|
||||
$#exploded_tokens = $i;
|
||||
@exploded_tokens;
|
||||
}
|
||||
|
||||
|
||||
|
||||
sub markup_line($)
|
||||
{
|
||||
my $line = shift;
|
||||
|
||||
local @exploded_phrases;
|
||||
local @exploded_tokens;
|
||||
|
||||
_explode_line($line);
|
||||
|
||||
$i = 0;
|
||||
foreach $phrase ( @exploded_phrases )
|
||||
{
|
||||
$phrase =~ s/&/&/g;
|
||||
$phrase =~ s/</</g;
|
||||
$phrase =~ s/>/>/g;
|
||||
|
||||
my $token = $exploded_tokens[$i];
|
||||
if ( defined $token && ($token_kind = $token_dictionary{$token}) >= 0 )
|
||||
{
|
||||
$phrase = $markup_prefix[$token_kind] . $phrase . $markup_suffix[$token_kind];
|
||||
}
|
||||
++$i;
|
||||
}
|
||||
|
||||
join '', @exploded_phrases;
|
||||
}
|
||||
|
||||
|
||||
sub add_token($$)
|
||||
{
|
||||
(my $token, my $token_kind) = @_;
|
||||
if ( !defined $token_dictionary{$token} || ($token_kind > $token_dictionary{$token}) )
|
||||
{
|
||||
$token_dictionary{$token} = $token_kind;
|
||||
}
|
||||
}
|
||||
|
||||
sub add_good_english($)
|
||||
{
|
||||
my $line = shift;
|
||||
|
||||
foreach $token ( tokenize_line($line) )
|
||||
{
|
||||
add_token($token, $$GOOD_TOKEN);
|
||||
|
||||
my $initial_char = substr($token, 0, 1);
|
||||
(my $remainder = substr($token, 1)) =~ s/[aeiouy]+//g;
|
||||
|
||||
$abbreviated_length = length($remainder) + 1;
|
||||
if ( $abbreviated_length != length($token) && $abbreviated_length > 2 )
|
||||
{
|
||||
add_token("$initial_char$remainder", $$GOOD_TOKEN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub _add_tokens($$)
|
||||
{
|
||||
(my $line, my $token_kind) = @_;
|
||||
|
||||
foreach $token ( tokenize_line($line) )
|
||||
{
|
||||
add_token($token, $token_kind);
|
||||
}
|
||||
}
|
||||
|
||||
sub add_good_words($)
|
||||
{
|
||||
_add_tokens(shift, $$GOOD_TOKEN);
|
||||
}
|
||||
|
||||
sub add_bad_words($)
|
||||
{
|
||||
_add_tokens(shift, $$BAD_TOKEN);
|
||||
}
|
||||
|
||||
sub add_names($)
|
||||
{
|
||||
_add_tokens(shift, $$NAME_TOKEN);
|
||||
}
|
||||
|
||||
1;
|
|
@ -0,0 +1,250 @@
|
|||
#!/usr/bonsaitools/bin/mysqltcl
|
||||
# -*- Mode: tcl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
source globals.tcl
|
||||
|
||||
# cmdtrace on
|
||||
|
||||
assert {![info exists checkinlist]}
|
||||
|
||||
set inheader 1
|
||||
set foundlogline 0
|
||||
|
||||
proc trim {str} {
|
||||
return [string trim $str]
|
||||
}
|
||||
|
||||
set filelist {}
|
||||
set log {}
|
||||
|
||||
set appendjunk {}
|
||||
set repository {/m/src}
|
||||
|
||||
|
||||
if {[cequal [lindex $argv 0] "-treeid"]} {
|
||||
lvarpop argv
|
||||
set forcetreeid [lvarpop argv]
|
||||
}
|
||||
|
||||
|
||||
# Stupid hack to make empty array
|
||||
set group(xyzzy) 1
|
||||
unset group(xyzzy)
|
||||
|
||||
|
||||
for_file line $argv {
|
||||
set line [trim $line]
|
||||
if {$inheader} {
|
||||
switch -glob -- $line {
|
||||
{} {
|
||||
set inheader 0
|
||||
}
|
||||
}
|
||||
} elseif {!$foundlogline} {
|
||||
switch -glob -- $line {
|
||||
{?|*} {
|
||||
append appendjunk "$line\n"
|
||||
lassign [split $line "|"] chtype date name repository dir \
|
||||
file version sticky branch addlines removelines
|
||||
set key [list $date $branch $repository $dir $name]
|
||||
lappend group($key) [list $file $version $addlines \
|
||||
$removelines $sticky]
|
||||
}
|
||||
{Tag|*} {
|
||||
set data [split $line "|"]
|
||||
lvarpop data
|
||||
set repository [lvarpop data]
|
||||
set tagtime [lvarpop data]
|
||||
set tagname [lvarpop data]
|
||||
regsub -all -- / $repository _ mungedname
|
||||
set filename "data/taginfo/$mungedname/[MungeTagName $tagname]"
|
||||
Lock
|
||||
if {[catch {set fid [open "$filename" "a"]}]} {
|
||||
catch {mkdir data/taginfo}
|
||||
catch {chmod 0777 data/taginfo}
|
||||
catch {mkdir data/taginfo/$mungedname}
|
||||
catch {chmod 0777 data/taginfo/$mungedname}
|
||||
set fid [open "$filename" "a"]
|
||||
}
|
||||
puts $fid "$tagtime|[join $data {|}]"
|
||||
close $fid
|
||||
catch {chmod 0666 $filename}
|
||||
Unlock
|
||||
}
|
||||
{LOGCOMMENT} {
|
||||
set foundlogline 1
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if {[cequal $line ":ENDLOGCOMMENT"]} {
|
||||
break
|
||||
}
|
||||
append log "$line\n"
|
||||
}
|
||||
}
|
||||
|
||||
set plainlog $log
|
||||
set log [html_quote [trim $log]]
|
||||
|
||||
|
||||
regsub -all -- {[0-9][0-9][0-9][0-9][0-9]*} $log $BUGSYSTEMEXPR log
|
||||
|
||||
|
||||
Lock
|
||||
LoadTreeConfig
|
||||
if {![info exists forcetreeid]} {
|
||||
regsub -all -- / $repository _ mungedname
|
||||
set filename "data/checkinlog$mungedname"
|
||||
set fid [open $filename "a"]
|
||||
catch {chmod 0666 $filename}
|
||||
puts $fid "[set appendjunk]LOGCOMMENT\n$plainlog\n:ENDLOGCOMMENT"
|
||||
close $fid
|
||||
|
||||
ConnectToDatabase
|
||||
AddToDatabase $appendjunk $plainlog
|
||||
|
||||
}
|
||||
Unlock
|
||||
|
||||
|
||||
if {[info exists forcetreeid]} {
|
||||
set treestocheck $forcetreeid
|
||||
} else {
|
||||
set treestocheck $treelist
|
||||
}
|
||||
|
||||
|
||||
foreach key [array names group] {
|
||||
lassign $key date branch repository dir name
|
||||
set branch2 [crange $branch 1 end]
|
||||
set files {}
|
||||
set fullinfo {}
|
||||
foreach i $group($key) {
|
||||
lassign $i file version addlines removelines
|
||||
lappend files $file
|
||||
lappend fullinfo $i
|
||||
}
|
||||
|
||||
foreach treeid $treestocheck {
|
||||
if {[info exists treeinfo($treeid,nobonsai)]} {
|
||||
continue
|
||||
}
|
||||
|
||||
if {![cequal $branch $treeinfo($treeid,branch)] && \
|
||||
![cequal $branch2 $treeinfo($treeid,branch)]} {
|
||||
continue
|
||||
}
|
||||
|
||||
if {![cequal $repository $treeinfo($treeid,repository)]} {
|
||||
continue
|
||||
}
|
||||
|
||||
LoadDirList
|
||||
|
||||
set okdir 0
|
||||
|
||||
# Sigh. We have some specific files listed as well as modules. So,
|
||||
# painfully go through *every* file we're checking in, and see if any
|
||||
# of them are ones we're interested in.
|
||||
|
||||
foreach f $files {
|
||||
set full $dir/$f
|
||||
foreach d $legaldirs {
|
||||
if {[string match $d $full]} {
|
||||
set okdir 1
|
||||
break
|
||||
}
|
||||
}
|
||||
if {$okdir} {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if {$okdir} {
|
||||
Lock
|
||||
catch {unset batchid}
|
||||
catch {unset checkinlist}
|
||||
LoadCheckins
|
||||
set id checkin-$date-[id process]
|
||||
lappend checkinlist $id
|
||||
upvar #0 $id foo
|
||||
set foo(person) $name
|
||||
set foo(date) $date
|
||||
set foo(dir) $dir
|
||||
set foo(files) $files
|
||||
set foo(log) $log
|
||||
set foo(treeopen) $treeopen
|
||||
set foo(fullinfo) $fullinfo
|
||||
WriteCheckins
|
||||
Log "Added checkin $name $dir $files"
|
||||
Unlock
|
||||
if {$treeopen} {
|
||||
set filename [DataDir]/openmessage
|
||||
foreach i $checkinlist {
|
||||
upvar #0 $i info
|
||||
if {[cequal $info(person) $name]} {
|
||||
if {![cequal $id $i]} {
|
||||
# This person already has a checkin, so we don't
|
||||
# need to bother him again.
|
||||
set filename thisFileDoesntExist
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
set filename [DataDir]/closemessage
|
||||
}
|
||||
if {![info exists forcetreeid] && [file exists $filename]} {
|
||||
set fid [open $filename "r"]
|
||||
set text [read $fid]
|
||||
close $fid
|
||||
set profile [GenerateProfileHTML $name]
|
||||
set nextclose {[We don't remember close times any more...]}
|
||||
foreach k {name dir files log profile nextclose} {
|
||||
regsub -all -- "%$k%" $text [set $k] text
|
||||
}
|
||||
exec /usr/lib/sendmail -t << $text
|
||||
Log "Mailed file $filename to $name"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NOTDEF {
|
||||
|
||||
set tmp $log
|
||||
|
||||
while {[regexp -nocase -- {.*bugfix([ 0-9]*)(.*)$} $tmp foo list tmp]} {
|
||||
set fileversions {}
|
||||
foreach i [array names group] {
|
||||
lassign $i file version
|
||||
lappend $fileversions [list $file $version]
|
||||
}
|
||||
foreach b $list {
|
||||
set result [exec /usr/local/bin/lynx -dump "http://scopus.mcom.com/terrsplat/doclosebug.cgi?id=$b&directory=$dir&fileversions=$fileversions&who=$name&log=$plainlog"]
|
||||
if {$result != "OK\n"} {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
exit
|
|
@ -0,0 +1,205 @@
|
|||
#!/usr/bonsaitools/bin/mysqltcl
|
||||
# -*- Mode: tcl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
source CGI.tcl
|
||||
|
||||
Lock
|
||||
LoadCheckins
|
||||
LoadMOTD
|
||||
LoadTreeConfig
|
||||
Unlock
|
||||
|
||||
puts "Content-type: text/html
|
||||
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Bonsai administration</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Bonsai administration</h1>
|
||||
|
||||
You realize, of course, that you have to know the magic password to do
|
||||
anything from here.
|
||||
|
||||
<hr>
|
||||
<a href=showcheckins.cgi?tweak=1[BatchIdPart]>Go tweak bunches of checkins at once.</a>
|
||||
<hr>
|
||||
|
||||
"
|
||||
|
||||
|
||||
puts "
|
||||
<FORM method=get action=\"doadmin.cgi\">
|
||||
<B>Password:</B> <INPUT NAME=password TYPE=password> <BR>
|
||||
<INPUT TYPE=HIDDEN NAME=treeid VALUE=$treeid>
|
||||
"
|
||||
|
||||
if {$treeopen} {
|
||||
puts "
|
||||
<INPUT TYPE=HIDDEN NAME=command VALUE=close>
|
||||
<B>Closing time stamp is:</B>
|
||||
<INPUT NAME=closetimestamp VALUE=\"[value_quote [MyFmtClock [getclock]]]\"><BR>
|
||||
<INPUT TYPE=SUBMIT VALUE=\"Close the tree\">
|
||||
"
|
||||
} else {
|
||||
puts "
|
||||
<INPUT TYPE=HIDDEN NAME=command VALUE=open>
|
||||
<B>The new \"good\" timestamp is:</B>
|
||||
<INPUT NAME=lastgood VALUE=\"[value_quote [MyFmtClock [getclock]]]\">
|
||||
<BR>
|
||||
<INPUT TYPE=CHECKBOX NAME=doclear CHECKED>Clear the list of checkins.<BR>
|
||||
<INPUT TYPE=SUBMIT VALUE=\"Open the tree\">
|
||||
"
|
||||
}
|
||||
puts "
|
||||
</FORM>
|
||||
|
||||
<hr>
|
||||
|
||||
<FORM method=get action=\"doadmin.cgi\">
|
||||
<B>Password:</B> <INPUT NAME=password TYPE=password> <BR>
|
||||
<INPUT TYPE=HIDDEN NAME=treeid VALUE=$treeid>
|
||||
<INPUT TYPE=HIDDEN NAME=command VALUE=tweaktimes>
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TD><B>Last good timestamp:</B></TD>
|
||||
<TD><INPUT NAME=lastgood VALUE=\"[value_quote [MyFmtClock $lastgoodtimestamp]]\"></TD>
|
||||
</TR><TR>
|
||||
|
||||
<TD><B>Last close timestamp:</B></TD>
|
||||
<TD><INPUT NAME=lastclose VALUE=\"[value_quote [MyFmtClock $closetimestamp]]\"></TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
<INPUT TYPE=SUBMIT VALUE=\"Tweak the timestamps\">
|
||||
</FORM>
|
||||
|
||||
|
||||
<hr>
|
||||
|
||||
<FORM method=get action=\"doadmin.cgi\">
|
||||
<INPUT TYPE=HIDDEN NAME=treeid VALUE=$treeid>
|
||||
<B>Password:</B> <INPUT NAME=password TYPE=password> <BR>
|
||||
<INPUT TYPE=HIDDEN NAME=command VALUE=editmotd>
|
||||
|
||||
Change the message-of-the-day:<br>
|
||||
<INPUT TYPE=HIDDEN NAME=origmotd VALUE=\"[value_quote $motd]\">
|
||||
<TEXTAREA NAME=motd ROWS=10 COLS=50>$motd</TEXTAREA><BR>
|
||||
<INPUT TYPE=SUBMIT VALUE=\"Change the MOTD\">
|
||||
</FORM>
|
||||
|
||||
|
||||
<hr>
|
||||
|
||||
<FORM method=get action=\"editmessage.cgi\">
|
||||
<INPUT TYPE=HIDDEN NAME=treeid VALUE=$treeid>
|
||||
|
||||
Change the e-mail message sent:
|
||||
<SELECT NAME=msgname SIZE=1>
|
||||
<OPTION VALUE=openmessage>when a checkin is made when the tree is open.
|
||||
<OPTION VALUE=closemessage>when a checkin is made when the tree is closed.
|
||||
<OPTION VALUE=treeopened>to the hook when the tree opens
|
||||
<OPTION VALUE=treeopenedsamehook>to the hook when the tree opens and the hook isn't cleared
|
||||
<OPTION VALUE=treeclosed>to the hook when the tree closes
|
||||
</SELECT>
|
||||
<br>
|
||||
<INPUT TYPE=SUBMIT VALUE=\"Edit a message\">
|
||||
|
||||
</FORM>
|
||||
|
||||
|
||||
<hr>
|
||||
|
||||
<FORM method=get action=\"repophook.cgi\">
|
||||
<INPUT TYPE=HIDDEN NAME=treeid VALUE=$treeid>
|
||||
<B>Password:</B> <INPUT NAME=password TYPE=password> <BR>
|
||||
<INPUT TYPE=HIDDEN NAME=command VALUE=repophook>
|
||||
Repopulate the hook from scratch.<p>
|
||||
<font color=red size=+2>This can be very dangerous.</font> You should
|
||||
usually only need to do this to populate a new Bonsai branch.
|
||||
<p>
|
||||
<b>Use any checkin since:</b>
|
||||
<INPUT NAME=startfrom VALUE=\"[value_quote [MyFmtClock $lastgoodtimestamp]]\">
|
||||
<br>
|
||||
<INPUT TYPE=SUBMIT VALUE=\"Rebuild the hook\">
|
||||
</FORM>
|
||||
|
||||
<hr>
|
||||
|
||||
<FORM method=get action=\"rebuildtaginfo.cgi\">
|
||||
<INPUT TYPE=HIDDEN NAME=treeid VALUE=$treeid>
|
||||
<B>Password:</B> <INPUT NAME=password TYPE=password> <BR>
|
||||
<INPUT TYPE=HIDDEN NAME=command VALUE=rebuildtaginfo>
|
||||
Recreate the entire table of tags for the $treeinfo($treeid,repository)
|
||||
repository from scratch.
|
||||
<p>
|
||||
<font color=red size=+2>This can take a very, very long time.</font> You
|
||||
should
|
||||
usually only need to do this when first introducing an entire CVS repository
|
||||
into Bonsai. (And, in fact, nothing right now ever even uses that info, so
|
||||
don't bother unless you know what you're doing.)
|
||||
<br>
|
||||
<INPUT TYPE=SUBMIT VALUE=\"Rebuild tag information\">
|
||||
</FORM>
|
||||
|
||||
<hr>
|
||||
|
||||
<FORM method=get action=\"rebuildcvshistory.cgi\">
|
||||
<INPUT TYPE=HIDDEN NAME=treeid VALUE=$treeid>
|
||||
<B>Password:</B> <INPUT NAME=password TYPE=password> <BR>
|
||||
<INPUT TYPE=HIDDEN NAME=command VALUE=rebuildcvs>
|
||||
Recreate the entire list of every checkin ever done to the
|
||||
$treeinfo($treeid,repository) repository from scratch.
|
||||
<p>
|
||||
<font color=red size=+2>This can take an incredibly long time.</font> You
|
||||
should
|
||||
usually only need to do this when first introducing an entire CVS repository
|
||||
into Bonsai.
|
||||
<p>
|
||||
<b>Ignore checkins earlier than:</b>
|
||||
<INPUT NAME=startfrom VALUE=\"[value_quote [MyFmtClock 0]]\">
|
||||
<br>
|
||||
<b>Ignore files before (must be full path starting with $treeinfo($treeid,repository); leave blank to do everything):</b>
|
||||
<INPUT NAME=firstfile VALUE=\"\" size=50>
|
||||
<br>
|
||||
<b>Only do files within the subdirectory of $treeinfo($treeid,repository) named:</b>
|
||||
<INPUT NAME=subdir VALUE=\".\" size=50>
|
||||
<br>
|
||||
<INPUT TYPE=SUBMIT VALUE=\"Rebuild cvs history\">
|
||||
</FORM>
|
||||
|
||||
<hr>
|
||||
<FORM method=post action=\"doadmin.cgi\">
|
||||
<INPUT TYPE=HIDDEN NAME=treeid VALUE=$treeid>
|
||||
<INPUT TYPE=HIDDEN NAME=command VALUE=changepassword>
|
||||
Change password.<BR>
|
||||
<B>Old password:</B> <INPUT NAME=password TYPE=password> <BR>
|
||||
<B>New password:</B> <INPUT NAME=newpassword TYPE=password> <BR>
|
||||
<B>Retype new password:</B> <INPUT NAME=newpassword2 TYPE=password> <BR>
|
||||
<INPUT TYPE=RADIO NAME=doglobal VALUE=0 CHECKED>Change password for this tree<BR>
|
||||
<INPUT TYPE=RADIO NAME=doglobal VALUE=1>Change master Bonsai password<BR>
|
||||
<INPUT TYPE=SUBMIT VALUE=\"Change the password\">
|
||||
</FORM>
|
||||
"
|
||||
|
||||
|
||||
PutsTrailer
|
||||
|
||||
exit
|
|
@ -0,0 +1,84 @@
|
|||
# -*- Mode: tcl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
proc AdminOpenTree {lastgood clearp} {
|
||||
global lastgoodtimestamp treeopen checkinlist
|
||||
if {$treeopen} {
|
||||
return
|
||||
}
|
||||
set lastgoodtimestamp $lastgood
|
||||
set treeopen 1
|
||||
PickNewBatchID
|
||||
if {$clearp} {
|
||||
SendMail treeopened
|
||||
set checkinlist {}
|
||||
} else {
|
||||
SendMail treeopenedsamehook
|
||||
}
|
||||
Log "Tree opened. lastgood is [MyFmtClock $lastgoodtimestamp]"
|
||||
}
|
||||
|
||||
|
||||
proc AdminCloseTree {closetime} {
|
||||
global closetimestamp treeopen
|
||||
if {!$treeopen} {
|
||||
return
|
||||
}
|
||||
set closetimestamp $closetime
|
||||
set treeopen 0
|
||||
SendMail treeclosed
|
||||
Log "Tree closed. closetime is [MyFmtClock $closetimestamp]"
|
||||
}
|
||||
|
||||
|
||||
proc MakeHookList {} {
|
||||
global checkinlist
|
||||
|
||||
# First, the hack to make an empty array.
|
||||
set people(zzz) 1
|
||||
unset people(zzz)
|
||||
|
||||
foreach c $checkinlist {
|
||||
upvar #0 $c info
|
||||
set people($info(person)) 1
|
||||
}
|
||||
|
||||
return [lsort [array names people]]
|
||||
}
|
||||
|
||||
|
||||
|
||||
proc SendMail {filename} {
|
||||
set hooklist [join [MakeHookList] ", "]
|
||||
if {[lempty $hooklist]} {
|
||||
return
|
||||
}
|
||||
|
||||
set fullfilename [DataDir]/$filename
|
||||
if {[file exists $fullfilename]} {
|
||||
set text [read_file $fullfilename]
|
||||
} else {
|
||||
set text ""
|
||||
}
|
||||
|
||||
foreach k {hooklist} {
|
||||
regsub -all -- "%$k%" $text [set $k] text
|
||||
}
|
||||
|
||||
exec /usr/lib/sendmail -t << $text
|
||||
}
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 20 KiB |
|
@ -0,0 +1,91 @@
|
|||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
# Query the CVS database.
|
||||
#
|
||||
$|=1;
|
||||
|
||||
print "Content-type: text/html
|
||||
|
||||
<HTML>";
|
||||
|
||||
require 'modules.pl';
|
||||
|
||||
|
||||
print "
|
||||
<HEAD>
|
||||
<TITLE>The CVS Branch Spammer (TM)</TITLE>
|
||||
</HEAD>
|
||||
<H1>The CVS Branch Spammer (TM)</H1>
|
||||
<p> Questions, Comments, Feature requests? mail <a href=mailto:ltabb>ltabb</a>
|
||||
<h3>What this tool does</h3>
|
||||
|
||||
<p>In the course of software development, it is necessary to form a branch
|
||||
to do development on for a period of time. Sometimes you want to merge these
|
||||
changes back into the trunk in one shot. Sometime you want to have the developers
|
||||
merge the changes themselves, individually. This tool makes sure the developers
|
||||
have merged their changes in individually.
|
||||
|
||||
<p>The CVS Branch Spammer goes out and figures out what changes were made on
|
||||
a branch and then looks to see if these changes where also made on the tip. It
|
||||
formulates a mail message and send the mail to the indivual developers. The
|
||||
individual developers look at the mail and reply that they have made their
|
||||
changes in the tip.
|
||||
|
||||
<p>To run this program answer the following questions and bonk the spam button.
|
||||
|
||||
|
||||
<p>
|
||||
<FORM METHOD=GET ACTION='branchspammer.cgi'>
|
||||
";
|
||||
|
||||
|
||||
#
|
||||
# module selector
|
||||
#
|
||||
print "
|
||||
|
||||
<nobr><b>Pick the name of the CVS Module you use to pull your source</b>
|
||||
<SELECT name='module' size=5>
|
||||
<OPTION SELECTED VALUE='all'>All Files in the Repository
|
||||
<OPTION SELECTED VALUE='Client40All'>Client40All
|
||||
";
|
||||
|
||||
#
|
||||
# Print out all the Different Modules
|
||||
#
|
||||
for $k (sort( keys( %$modules ) ) ){
|
||||
print "<OPTION value='$k'>$k\n";
|
||||
}
|
||||
|
||||
print "</SELECT></NOBR>\n";
|
||||
|
||||
#
|
||||
# Branch
|
||||
#
|
||||
print "<br><nobr><b>What is the name of your branch:</b> <input type=text name=branch size=25></nobr>\n";
|
||||
|
||||
print "<br><nobr><b>Who should the email message be from?:</b> <input type=text name=whofrom size=25></nobr>\n";
|
||||
|
||||
print "
|
||||
<br>
|
||||
<br>
|
||||
<INPUT TYPE=SUBMIT VALUE='Run the Branchspammer'>
|
||||
</FORM>";
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
|
||||
require 'lloydcgi.pl';
|
||||
require 'timelocal.pl';
|
||||
require 'cvsquery.pl';
|
||||
|
||||
$| = 1;
|
||||
|
||||
print "Content-type: text/html
|
||||
|
||||
<HTML>";
|
||||
|
||||
$CHECKIN_DATA_FILE = 'data/checkinlog_m_src';
|
||||
$CHECKIN_INDEX_FILE = 'data/index_m_src';
|
||||
|
||||
#
|
||||
# build a module map
|
||||
#
|
||||
$query_module = $form{'module'};
|
||||
|
||||
@query_dirs = split(/[;, \t]+/, $form{'dir'});
|
||||
|
||||
$query_date_type = $form{'date'};
|
||||
$query_date_min = time-(24*60*60*15);
|
||||
$query_who ='' ;
|
||||
$query_branch = $form{'branch'};
|
||||
|
||||
|
||||
print "<h1>Running Query, this may take a while...</h1>";
|
||||
|
||||
$result= &query_checkins( $mod_map );
|
||||
|
||||
#
|
||||
# Test code to print the results
|
||||
#
|
||||
|
||||
if( 0 ) {
|
||||
if( $form{"sortby"} eq "Who" ){
|
||||
$result = [sort {
|
||||
$a->[$CI_WHO] cmp $b->[$CI_WHO]
|
||||
|| $b->[$CI_DATE] <=> $a->[$CI_DATE]
|
||||
} @{$result}] ;
|
||||
$head_who = $SORT_HEAD;
|
||||
}
|
||||
elsif( $form{"sortby"} eq "File" ){
|
||||
$result = [sort {
|
||||
$a->[$CI_FILE] cmp $b->[$CI_FILE]
|
||||
|| $b->[$CI_DATE] <=> $a->[$CI_DATE]
|
||||
|| $a->[$CI_DIRECTORY] cmp $b->[$CI_DIRECTORY]
|
||||
} @{$result}] ;
|
||||
$head_file = $SORT_HEAD;
|
||||
}
|
||||
elsif( $form{"sortby"} eq "Directory" ){
|
||||
$result = [sort {
|
||||
$a->[$CI_DIRECTORY] cmp $b->[$CI_DIRECTORY]
|
||||
|| $a->[$CI_FILE] cmp $b->[$CI_FILE]
|
||||
|| $b->[$CI_DATE] <=> $a->[$CI_DATE]
|
||||
} @{$result}] ;
|
||||
$head_directory = $SORT_HEAD;
|
||||
}
|
||||
elsif( $form{"sortby"} eq "Change Size" ){
|
||||
$result = [sort {
|
||||
|
||||
($b->[$CI_LINES_ADDED]- $b->[$CI_LINES_REMOVED])
|
||||
<=> ($a->[$CI_LINES_ADDED]- $a->[$CI_LINES_REMOVED])
|
||||
#|| $b->[$CI_DATE] <=> $a->[$CI_DATE]
|
||||
} @{$result}] ;
|
||||
$head_delta = $SORT_HEAD;
|
||||
}
|
||||
else{
|
||||
$result = [sort {$b->[$CI_DATE] <=> $a->[$CI_DATE]} @{$result}] ;
|
||||
$head_date = $SORT_HEAD;
|
||||
}
|
||||
}
|
||||
|
||||
print "<pre>";
|
||||
for $ci (@$result) {
|
||||
$ci->[$CI_LOG] = '';
|
||||
$s = join("|",@$ci);
|
||||
print "$s\n";
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
From: bonsai-daemon
|
||||
To: %name%
|
||||
Subject: [Bonsai] Hey! You checked in while the tree was closed!
|
||||
Mime-Version: 1.0
|
||||
Content-Type: text/html
|
||||
|
||||
<HTML>
|
||||
|
||||
<H1>Boy, you better have had permission!</H1>
|
||||
|
||||
You just checked into <tt>%dir%</tt> the files <tt>%files%</tt>. The
|
||||
tree is currently frozen. You better have had permission from the build group
|
||||
to make a checkin; otherwise, you're in deep doo-doo.
|
||||
|
||||
<P>
|
||||
|
||||
Your contact info and other vital data is listed below. Please
|
||||
<a href=http://warp/bonsai/profile.cgi?person=%name%>update</a>
|
||||
this info <b>immediately</b> if it is at all inaccurate or incorrect.
|
||||
|
||||
<hr>
|
||||
|
||||
%profile%
|
|
@ -0,0 +1,27 @@
|
|||
<html> <head>
|
||||
<title>Changing other people's contact info.</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Changing other people's contact info.</h1>
|
||||
|
||||
Occasionally, you need to change the "contact info" listed for some
|
||||
other person. (Like, they just called you on their celphone from the
|
||||
horrible traffic accident they just got in, and need you to go on the
|
||||
hook for them.) Well, it's easy. Go ahead onto their contact page,
|
||||
change the contact info field, and type your own username and UNIX
|
||||
password to the form. It'll work.
|
||||
<P>
|
||||
Note that you're only allowed to change the "Current Contact Info"
|
||||
field this way. It won't let you change anything else.
|
||||
|
||||
<hr>
|
||||
|
||||
<a href="toplevel.cgi" target=_top>Back to the top of Bonsai</a>
|
||||
|
||||
<hr>
|
||||
<address><a href="http://home.netscape.com/people/terry/">Terry Weissman <terry@netscape.com></a></address>
|
||||
<!-- hhmts start -->
|
||||
Last modified: Wed Oct 30 13:03:35 1996
|
||||
<!-- hhmts end -->
|
||||
</body> </html>
|
|
@ -0,0 +1,88 @@
|
|||
#!/usr/bonsaitools/bin/mysqltcl
|
||||
# -*- Mode: tcl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
source CGI.tcl
|
||||
|
||||
set maxsize 400
|
||||
|
||||
LoadCheckins
|
||||
|
||||
puts "Content-type: text/html
|
||||
|
||||
<HTML>
|
||||
<TITLE>Beancounter central.</TITLE>
|
||||
|
||||
<H1>Meaningless checkin statistics</H1>
|
||||
|
||||
<TABLE BORDER CELLSPACING=2><TR>
|
||||
<TH>Tree closed</TH>
|
||||
<TH>Number<BR>of<BR>people<BR>making<BR>changes</TH>
|
||||
<TH COLSPAN=2>Number of checkins</TH>
|
||||
</TR>
|
||||
"
|
||||
|
||||
set list {}
|
||||
|
||||
|
||||
foreach i [glob "[DataDir]/batch-*\[0-9\]"] {
|
||||
regexp -- {[0-9]*$} $i n
|
||||
lappend list $n
|
||||
}
|
||||
|
||||
set list [lsort -integer -decreasing $list]
|
||||
|
||||
set first 1
|
||||
|
||||
set biggest 1
|
||||
|
||||
foreach i $list {
|
||||
source [DataDir]/batch-$i
|
||||
set num($i) [llength $checkinlist]
|
||||
if {$num($i) > $biggest} {
|
||||
set biggest $num($i)
|
||||
}
|
||||
if {$first} {
|
||||
set donetime($i) "Current hook"
|
||||
set first 0
|
||||
} else {
|
||||
set donetime($i) [MyFmtClock $closetimestamp]
|
||||
}
|
||||
catch {unset people}
|
||||
set people(zzz) 1
|
||||
unset people(zzz)
|
||||
foreach c $checkinlist {
|
||||
upvar #0 $c info
|
||||
set people($info(person)) 1
|
||||
}
|
||||
set numpeople($i) [array size people]
|
||||
}
|
||||
|
||||
foreach i $list {
|
||||
puts "<TR>"
|
||||
puts "<TD>$donetime($i)</TD>"
|
||||
puts "<TD ALIGN=RIGHT>$numpeople($i)</TD>"
|
||||
puts "<TD ALIGN=RIGHT>$num($i)</TD>"
|
||||
puts "<TD><table WIDTH=[expr $num($i) * $maxsize / $biggest] bgcolor=green><tr><td> </td></tr></table></TD>"
|
||||
puts "</TR>"
|
||||
}
|
||||
puts "</TABLE>"
|
||||
|
||||
PutsTrailer
|
||||
|
||||
exit
|
|
@ -0,0 +1,93 @@
|
|||
#!/usr/bonsaitools/bin/mysqltcl
|
||||
# -*- Mode: tcl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
source globals.tcl
|
||||
|
||||
set treeid [lindex $argv 0]
|
||||
LoadTreeConfig
|
||||
set modulename $treeinfo($treeid,module)
|
||||
|
||||
Log "Attempting to recreate legaldirs..."
|
||||
|
||||
proc digest {str} {
|
||||
global array
|
||||
set key [lvarpop str]
|
||||
if {[cequal [cindex [lindex $str 0] 0] "-"]} {
|
||||
lvarpop str
|
||||
}
|
||||
set array($key) $str
|
||||
}
|
||||
|
||||
|
||||
|
||||
set env(CVSROOT) $treeinfo($treeid,repository)
|
||||
set origdir [pwd]
|
||||
cd /
|
||||
set fid [open "|/tools/ns/bin/cvs checkout -c" r]
|
||||
cd $origdir
|
||||
|
||||
set curline ""
|
||||
while {[gets $fid line] >= 0} {
|
||||
if {[ctype space [cindex $line 0]]} {
|
||||
append curline $line
|
||||
} else {
|
||||
digest $curline
|
||||
set curline $line
|
||||
}
|
||||
}
|
||||
digest $curline
|
||||
close $fid
|
||||
|
||||
if {![info exists array($modulename)]} {
|
||||
error "modules file no longer includes $modulename ???"
|
||||
}
|
||||
|
||||
set oldlist {}
|
||||
set list $modulename
|
||||
|
||||
while {![cequal $list $oldlist]} {
|
||||
set oldlist $list
|
||||
set list {}
|
||||
foreach i $oldlist {
|
||||
if {[info exists array($i)]} {
|
||||
set list [concat $list $array($i)]
|
||||
# Do an unset to prevent infinite recursion.
|
||||
unset array($i)
|
||||
} else {
|
||||
lappend list $i
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Lock
|
||||
set fid [open "[DataDir]/legaldirs" "w"]
|
||||
catch {chmod 0666 "[DataDir]/legaldirs"}
|
||||
foreach i $list {
|
||||
puts $fid $i
|
||||
puts $fid "$i/*"
|
||||
}
|
||||
close $fid
|
||||
Log "...legaldirs recreated."
|
||||
Unlock
|
||||
|
||||
exit
|
|
@ -0,0 +1,599 @@
|
|||
#!/usr/bonsaitools/bin/perl --
|
||||
# cvsblame.cgi -- cvsblame with logs as popups and allowing html in comments.
|
||||
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
|
||||
# Created: Steve Lamm <slamm@netscape.com>, 12-Sep-97.
|
||||
# Modified: Marc Byrd <byrd@netscape.com> , 19971030.
|
||||
#
|
||||
# Arguments (passed via GET or POST):
|
||||
# file - path to file name (e.g. ns/cmd/xfe/Makefile)
|
||||
# root - cvs root (e.g. /warp/webroot)
|
||||
# - default includes /m/src/ and /h/rodan/cvs/repository/1.0
|
||||
# rev - revision (default is the latest version)
|
||||
# line_nums - boolean for line numbers on/off (use 1,0).
|
||||
# (1,on by default)
|
||||
# use_html - boolean for html comments on/off (use 1,0).
|
||||
# (0,off by default)
|
||||
# sanitize - path to sanitization dictionary
|
||||
# (e.g. /warp2/webdoc/projects/bonsai/dictionary/sanitization.db)
|
||||
# mark - highlight a line
|
||||
#
|
||||
|
||||
require 'lloydcgi.pl';
|
||||
require 'cvsblame.pl';
|
||||
require 'utils.pl';
|
||||
use SourceChecker;
|
||||
|
||||
$| = 1;
|
||||
|
||||
# Cope with the cookie and print the header, first thing. That way, if
|
||||
# any errors result, they will show up for the user.
|
||||
|
||||
print "Content-Type:text/html\n";
|
||||
if ($ENV{"REQUEST_METHOD"} eq 'POST' && defined($form{'set_line'})) {
|
||||
# Expire the cookie 5 months from now
|
||||
print "Set-Cookie: line_nums=$form{'set_line'}; expires="
|
||||
. toGMTString(time + 86400 * 152) . "; path=/\n";
|
||||
}
|
||||
print "\n";
|
||||
|
||||
|
||||
# Some Globals
|
||||
#
|
||||
|
||||
@src_roots = getRepositoryList();
|
||||
|
||||
# Init sanitiazation source checker
|
||||
#
|
||||
$sanitization_dictionary = $form{'sanitize'};
|
||||
$opt_sanitize = defined $sanitization_dictionary;
|
||||
if ( $opt_sanitize )
|
||||
{
|
||||
dbmopen %SourceChecker::token_dictionary, "$sanitization_dictionary", 0664;
|
||||
}
|
||||
|
||||
# Init byrd's 'feature' to allow html in comments
|
||||
#
|
||||
$opt_html_comments = &html_comments_init();
|
||||
|
||||
|
||||
# Handle the "file" argument
|
||||
#
|
||||
$filename = '';
|
||||
$filename = $form{'file'} if defined($form{'file'});
|
||||
if ($filename eq '')
|
||||
{
|
||||
&print_usage;
|
||||
exit;
|
||||
}
|
||||
($file_head, $file_tail) = $filename =~ m@(.*/)?(.+)@;
|
||||
|
||||
# Handle the "rev" argument
|
||||
#
|
||||
$opt_rev = $form{'rev'} if defined($form{'rev'} && $form{'rev'} ne 'HEAD');
|
||||
$browse_revtag = "HEAD";
|
||||
$browse_revtag = $opt_rev if ($opt_rev =~ /[A-Za-z]/);
|
||||
$revision = '';
|
||||
|
||||
|
||||
# Handle the "root" argument
|
||||
#
|
||||
if (defined($root = $form{'root'}) && $root ne '') {
|
||||
$root =~ s|/$||;
|
||||
validateRepository($root);
|
||||
if (-d $root) {
|
||||
unshift(@src_roots, $root);
|
||||
} else {
|
||||
&print_top;
|
||||
print "Error: Root, $root, is not a directory.<BR><BR>\n";
|
||||
print "</BODY></HTML>\n";
|
||||
&print_bottom;
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Find the rcs file
|
||||
#
|
||||
foreach (@src_roots) {
|
||||
$root = $_;
|
||||
$rcs_filename = "$root/$filename,v";
|
||||
goto found_file if -r $rcs_filename;
|
||||
$rcs_filename = "$root/${file_head}Attic/$file_tail,v";
|
||||
goto found_file if -r $rcs_filename;
|
||||
}
|
||||
# File not found
|
||||
&print_top;
|
||||
print "Rcs file, $filename, does not exist.<BR><BR>\n";
|
||||
print "</BODY></HTML>\n";
|
||||
&print_bottom;
|
||||
exit;
|
||||
|
||||
found_file:
|
||||
($rcs_path) = $rcs_filename =~ m@$root/(.*)/.+?,v@;
|
||||
|
||||
# Parse the rcs file ($opt_rev is passed as a global)
|
||||
#
|
||||
$revision = &parse_cvs_file($rcs_filename);
|
||||
$file_rev = $revision;
|
||||
|
||||
# Handle the "line_nums" argument
|
||||
#
|
||||
$opt_line_nums = 0;
|
||||
$opt_line_nums = 1 if $cookie_jar{'line_nums'} eq 'on';
|
||||
$opt_line_nums = 0 if $form{'line_nums'} =~ /off|no|0/i;
|
||||
$opt_line_nums = 1 if $form{'line_nums'} =~ /on|yes|1/i;
|
||||
|
||||
# Option to make links to included files
|
||||
$opt_includes = 0;
|
||||
$opt_includes = 1 if $form{'includes'} =~ /on|yes|1/i;
|
||||
$opt_includes = 1 if $opt_includes && $file_tail =~ /(.c|.h|.cpp)$/;
|
||||
|
||||
@text = &extract_revision($revision);
|
||||
die "$progname: Internal consistency error" if ($#text != $#revision_map);
|
||||
|
||||
|
||||
# Handle the "mark" argument
|
||||
#
|
||||
$mark_arg = '';
|
||||
$mark_arg = $form{'mark'} if defined($form{'mark'});
|
||||
foreach $mark (split(',',$mark_arg)) {
|
||||
if (($begin, $end) = $mark =~ /(\d*)\-(\d*)/) {
|
||||
$begin = 1 if $begin eq '';
|
||||
$end = $#text + 1 if $end eq '' || $end > $#text + 1;
|
||||
next if $begin >= $end;
|
||||
$mark_line{$begin} = 'begin';
|
||||
$mark_line{$end} = 'end';
|
||||
} else {
|
||||
$mark_line{$mark} = 'single';
|
||||
}
|
||||
}
|
||||
|
||||
# Start printing out the page
|
||||
#
|
||||
&print_top;
|
||||
|
||||
if ($ENV{'HTTP_USER_AGENT'} =~ /Win/) {
|
||||
$font_tag = "<PRE><FONT FACE='Lucida Console' SIZE=-1>";
|
||||
} else {
|
||||
# We don't want your stinking Windows font
|
||||
#$font_tag = "<FONT>";
|
||||
$font_tag = "<PRE><FONT>";
|
||||
}
|
||||
|
||||
# Print link at top for directory browsing
|
||||
#
|
||||
$output = "<DIV ALIGN=LEFT>";
|
||||
foreach $path (split('/',$rcs_path)) {
|
||||
$link_path .= $path;
|
||||
$output .= "<A HREF='rview.cgi?dir=$link_path";
|
||||
$output .= "&cvsroot=$form{'root'}" if defined $form{'root'};
|
||||
$output .= "&rev=$browse_revtag" unless $browse_revtag eq 'HEAD';
|
||||
$output .= "' onmouseover='window.status=\"Browse $link_path\";"
|
||||
." return true;'>$path</A>/ ";
|
||||
$link_path .= '/';
|
||||
}
|
||||
$output .= "$file_tail "
|
||||
." (<A HREF onclick='return dif(\"$prev_revision{$revision}\",\"$revision\");'"
|
||||
." onmouseover='return log(event,0,\"$prev_revision{$revision}\","
|
||||
."\"$revision\");'>";
|
||||
$output .= "$browse_revtag:" unless $browse_revtag eq 'HEAD';
|
||||
$output .= $revision if $revision;
|
||||
$output .= "</A>)";
|
||||
|
||||
$output .= "</DIV>";
|
||||
EmitHtmlHeader("CVS Blame", $output);
|
||||
print "<HR>\n";
|
||||
|
||||
print $font_tag;
|
||||
|
||||
# Print each line of the revision, preceded by its annotation.
|
||||
#
|
||||
$start_of_mark = 0;
|
||||
$end_of_mark = 0;
|
||||
$line_num_width = int(log($#revision_map)/log(10)) + 1;
|
||||
$revision_width = 3;
|
||||
$author_width = 5;
|
||||
$line = 0;
|
||||
$usedlog{$revision} = 1;
|
||||
foreach $revision (@revision_map)
|
||||
{
|
||||
$text = $text[$line++];
|
||||
$usedlog{$revision} = 1;
|
||||
|
||||
|
||||
if ($opt_html_comments) {
|
||||
# Don't escape HTML in C/C++ comments
|
||||
$text = &leave_html_comments($text);
|
||||
} elsif ( $opt_sanitize ){
|
||||
# Mark filty words and Escape HTML meta-characters
|
||||
$text = markup_line($text);
|
||||
} else {
|
||||
$text =~ s/&/&/g;
|
||||
$text =~ s/</</g;
|
||||
$text =~ s/>/>/g;
|
||||
}
|
||||
# Add a link to traverse to included files
|
||||
$text = &link_includes($text) if $opt_includes;
|
||||
|
||||
|
||||
$output = "<A NAME=$line></A>";
|
||||
|
||||
# Highlight lines
|
||||
if (defined($mark_cmd = $mark_line{$line})
|
||||
&& $mark_cmd ne 'end') {
|
||||
|
||||
$output .= "<TABLE BORDER=0 CELLPADDING=0 CELLSPACING=0 "
|
||||
."><TR><TD BGCOLOR=LIGHTGREEN WIDTH='100%'>$font_tag";
|
||||
}
|
||||
|
||||
$output .= sprintf("%${line_num_width}s ", $line) if $opt_line_nums;
|
||||
|
||||
if ($old_revision ne $revision || $rev_count > 20) {
|
||||
|
||||
$author_width = max($author_width,length($revision_author{$revision}));
|
||||
$revision_width = max($revision_width,length($revision));
|
||||
|
||||
$output .= ($rev_count > 20 ? '| ' : '+ ');
|
||||
|
||||
$output .= sprintf("%-${author_width}s ",$revision_author{$revision});
|
||||
|
||||
$output .= "<A HREF "
|
||||
."onclick='return dif(\"$prev_revision{$revision}\",\"$revision\");' "
|
||||
."onmouseover='return log(event,$line,\"$prev_revision{$revision}\","
|
||||
."\"$revision\");'>$revision</A> ";
|
||||
$output .= ' ' x ($revision_width - length($revision));
|
||||
|
||||
$old_revision = $revision;
|
||||
$rev_count = 0;
|
||||
} else {
|
||||
$output .= '| ' . ' ' x ($author_width + $revision_width);
|
||||
}
|
||||
$rev_count++;
|
||||
|
||||
$output .= "$text";
|
||||
|
||||
# Close the highlighted section
|
||||
if (defined($mark_cmd) && $mark_cmd ne 'begin') {
|
||||
chop($output);
|
||||
$output .= "</TD>";
|
||||
#if( defined($prev_revision{$file_rev})) {
|
||||
$output .= "<TD ALIGN=RIGHT><A HREF=\"cvsblame.cgi?file=$filename&rev=$prev_revision{$file_rev}&root=$root&mark=$mark_arg\">Previous Revision ($prev_revision{$file_rev})</A></TD><TD BGCOLOR=LIGHTGREEN> </TD>";
|
||||
#}
|
||||
$output .= "</TR></TABLE>";
|
||||
}
|
||||
|
||||
print $output;
|
||||
}
|
||||
print "</FONT></PRE>\n";
|
||||
|
||||
# Write out cvs log messages as a JS variables
|
||||
#
|
||||
print "<SCRIPT>";
|
||||
while (($revision, $junk) = each %usedlog) {
|
||||
|
||||
# Create a safe variable name for a revision log
|
||||
$revisionName = $revision;
|
||||
$revisionName =~ tr/./_/;
|
||||
|
||||
$log = $revision_log{$revision};
|
||||
$log =~ s/([^\n\r]{80})([^\n\r]*)/$1\n$2/g;
|
||||
eval ('$log =~ s@\d{4,6}@' . $BUGSYSTEMEXPR . '@g;');
|
||||
$log =~ s/\n|\r|\r\n/<BR>/g;
|
||||
$log =~ s/"/\\"/g;
|
||||
|
||||
# Write JavaScript variable for log entry (e.g. log1_1 = "New File")
|
||||
print "log$revisionName = \""
|
||||
."$revision_ctime{$revision}<BR>"
|
||||
."<SPACER TYPE=VERTICAL SIZE=5>$log\";\n";
|
||||
}
|
||||
print "</SCRIPT>";
|
||||
|
||||
&print_bottom;
|
||||
|
||||
print "<NOLAYER><BR><FONT SIZE=-1>(This page is much cooler with a layers enabled browser)</FONT></NOLAYER>";
|
||||
|
||||
if ( $opt_sanitize )
|
||||
{
|
||||
dbmclose %SourceChecker::token_dictionary;
|
||||
}
|
||||
|
||||
## END of main script
|
||||
|
||||
sub max {
|
||||
local ($a, $b) = @_;
|
||||
return ($a > $b ? $a : $b);
|
||||
}
|
||||
|
||||
sub print_top {
|
||||
local ($title_text) = "for $file_tail (";
|
||||
$title_text .= "$browse_revtag:" unless $browse_revtag eq 'HEAD';
|
||||
$title_text .= $revision if $revision;
|
||||
$title_text .= ")";
|
||||
$title_text =~ s/\(\)//;
|
||||
|
||||
local ($diff_dir_link) =
|
||||
"cvsview2.cgi?subdir=$rcs_path&files=$file_tail&command=DIRECTORY";
|
||||
$diff_dir_link .= "&root=$form{'root'}" if defined $form{'root'};
|
||||
$diff_dir_link .= "&branch=$browse_revtag" unless $browse_revtag eq 'HEAD';
|
||||
|
||||
local ($diff_link) = "cvsview2.cgi?diff_mode=context&whitespace_mode=show";
|
||||
$diff_link .= "&root=$form{'root'}" if defined $form{'root'};
|
||||
$diff_link .= "&subdir=$rcs_path&command=DIFF_FRAMESET&file=$file_tail";
|
||||
|
||||
print <<__TOP__;
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>CVS Blame $title_text</TITLE>
|
||||
<SCRIPT>
|
||||
document.loaded = false;
|
||||
|
||||
function revToName (rev) {
|
||||
revName = rev + "";
|
||||
revArray = revName.split(".");
|
||||
return revArray.join("_");
|
||||
}
|
||||
|
||||
function finishedLoad() {
|
||||
if (parseInt(navigator.appVersion) < 4) {
|
||||
return true;
|
||||
}
|
||||
document.loaded = true;
|
||||
document.layers['popup'].visibility='hide';
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function log(event, line, prev_rev, rev) {
|
||||
window.defaultStatus = "";
|
||||
if (prev_rev == '') {
|
||||
window.status = "View diffs for " + file_tail;
|
||||
} else {
|
||||
window.status = "View diff for " + prev_rev + " vs." + rev;
|
||||
}
|
||||
|
||||
if (parseInt(navigator.appVersion) < 4) {
|
||||
return true;
|
||||
}
|
||||
|
||||
l = document.layers['popup'];
|
||||
if (document.loaded) {
|
||||
l.document.write("<TABLE BORDER=1 CELLSPACING=1 CELLPADDING=2><TR><TD>");
|
||||
if (line) {
|
||||
l.document.write("line " + line + ", ");
|
||||
}
|
||||
l.document.write(eval("log" + revToName(rev)) + "</TD></TR></TABLE>");
|
||||
l.document.close();
|
||||
}
|
||||
l.top = event.target.y - 3;
|
||||
l.left = event.target.x + 40;
|
||||
l.visibility="show";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function dif(prev_rev, rev) {
|
||||
if (prev_rev == '') {
|
||||
document.location = "$diff_dir_link";
|
||||
} else {
|
||||
document.location = "$diff_link"
|
||||
+ "&rev1=" + prev_rev + "&rev2=" + rev;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
file_tail = "$file_tail";
|
||||
|
||||
/* Make JavaScript happy in akbar */
|
||||
event = 0;
|
||||
initialLayer = "<TABLE BORDER=1 CELLSPACING=1 CELLPADDING=1><TR><TD><B>Page loading...please wait.</B></TD></TR></TABLE>";
|
||||
|
||||
</SCRIPT>
|
||||
</HEAD>
|
||||
<BODY onLoad="finishedLoad();">
|
||||
<LAYER SRC="javascript:initialLayer" NAME='popup' onMouseOut="this.visibility='hide';" LEFT=0 TOP=0 BGCOLOR='#FFFFFF' VISIBILITY='hide'></LAYER>
|
||||
__TOP__
|
||||
} # print_top
|
||||
|
||||
sub print_usage {
|
||||
local ($linenum_message) = '';
|
||||
local ($new_linenum, $src_roots_list);
|
||||
local ($title_text) = "Usage";
|
||||
|
||||
if ($ENV{"REQUEST_METHOD"} eq 'POST' && defined($form{'set_line'})) {
|
||||
|
||||
# Expire the cookie 5 months from now
|
||||
$set_cookie = "Set-Cookie: line_nums=$form{'set_line'}; expires="
|
||||
.&toGMTString(time + 86400 * 152)."; path=/";
|
||||
}
|
||||
if (!defined($cookie_jar{'line_nums'}) && !defined($form{'set_line'})) {
|
||||
$new_linenum = 'on';
|
||||
} elsif ($cookie_jar{'line_nums'} eq 'off' || $form{'set_line'} eq 'off') {
|
||||
$linenum_message = 'Line numbers are currently <b>off</b>.';
|
||||
$new_linenum = 'on';
|
||||
} else {
|
||||
$linenum_message = 'Line numbers are currently <b>on</b>.';
|
||||
$new_linenum = 'off';
|
||||
}
|
||||
$src_roots_list = join('<BR>', @src_roots);
|
||||
|
||||
print <<__USAGE__;
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>CVS Blame $title_text</TITLE>
|
||||
</HEAD><BODY>
|
||||
<H2>CVS Blame Usage</H2>
|
||||
Add parameters to the query string to view a file.
|
||||
<P>
|
||||
<TABLE BORDER CELLPADDING=3>
|
||||
<TR ALIGN=LEFT>
|
||||
<TH>Param</TH>
|
||||
<TH>Default</TH>
|
||||
<TH>Example</TH>
|
||||
<TH>Description</TH>
|
||||
</TR><TR>
|
||||
<TD>file</TD>
|
||||
<TD>--</TD>
|
||||
<TD>ns/cmd/Makefile</TD>
|
||||
<TD>path to file name</TD>
|
||||
</TR><TR>
|
||||
<TD>root</TD>
|
||||
<TD>$src_roots_list</TD>
|
||||
<TD>/warp/webroot</TD>
|
||||
<TD>cvs root</TD>
|
||||
</TR><TR>
|
||||
<TD>rev</TD>
|
||||
<TD>HEAD</TD>
|
||||
<TD>1.3
|
||||
<BR>ACTRA_branch</TD>
|
||||
<TD>revision</TD>
|
||||
</TR><TR>
|
||||
<TD>line_nums</TD>
|
||||
<TD>off *</TD>
|
||||
<TD>on
|
||||
<BR>off</TD>
|
||||
<TD>line numbers</TD>
|
||||
</TR><TR>
|
||||
<TD>#<line_number></TD>
|
||||
<TD>--</TD>
|
||||
<TD>#111</TD>
|
||||
<TD>jump to a line</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
<P>Examples:
|
||||
<TABLE><TR><TD> </TD><TD>
|
||||
<A HREF="cvsblame.cgi?file=ns/cmd/Makefile">
|
||||
cvsblame.cgi?file=ns/cmd/Makefile</A>
|
||||
</TD></TR><TR><TD> </TD><TD>
|
||||
<A HREF="cvsblame.cgi?file=ns/cmd/xfe/mozilla.c&rev=Dogbert4xEscalation_BRANCH">
|
||||
cvsblame.cgi?file=ns/cmd/xfe/mozilla.c&rev=Dogbert4xEscalation_BRANCH</A>
|
||||
</TD></TR><TR><TD> </TD><TD>
|
||||
<A HREF="cvsblame.cgi?file=projects/bonsai/cvsblame.cgi&root=/warp/webroot">
|
||||
cvsblame.cgi?file=projects/bonsai/cvsblame.cgi&root=/warp/webroot</A>
|
||||
</TD></TR><TR><TD> </TD><TD>
|
||||
<A HREF="cvsblame.cgi?file=ns/config/config.mk&line_nums=on">
|
||||
cvsblame.cgi?file=ns/config/config.mk&line_nums=on</A>
|
||||
</TD></TR><TR><TD> </TD><TD>
|
||||
<A HREF="cvsblame.cgi?file=ns/cmd/xfe/dialogs.c#2384">
|
||||
cvsblame.cgi?file=ns/cmd/xfe/dialogs.c#2384</A>
|
||||
</TD></TR></TABLE>
|
||||
|
||||
<P>
|
||||
You may also begin a query with the <A HREF="cvsqueryform.cgi">CVS Query Form</A>.
|
||||
<FORM METHOD='POST' ACTION='cvsblame.cgi'>
|
||||
|
||||
<TABLE CELLPADDING=0 CELLSPACING=0>
|
||||
<TR>
|
||||
<TD>*<SPACER TYPE=HORIZONTAL SIZE=6></TD>
|
||||
<TD>Instead of the <i>line_nums</i> parameter, you can
|
||||
<INPUT TYPE=submit value='set a cookie to turn $new_linenum'>
|
||||
line numbers.</TD>
|
||||
</TR><TR>
|
||||
<TD></TD>
|
||||
<TD>$linenum_message</TD>
|
||||
</TR></TABLE>
|
||||
|
||||
<INPUT TYPE=hidden NAME='set_line' value='$new_linenum'>
|
||||
</FORM>
|
||||
__USAGE__
|
||||
&print_bottom;
|
||||
} # sub print_usage
|
||||
|
||||
sub print_bottom {
|
||||
print <<__BOTTOM__;
|
||||
<HR WIDTH="100%">
|
||||
<FONT SIZE=-1>
|
||||
<A HREF="cvsblame.cgi">Page configuration and help</A>.
|
||||
Mail feedback to <A HREF="mailto:slamm?subject=About the cvsblame script"><slamm\@netscape.com></A>.
|
||||
</FONT></BODY>
|
||||
</HTML>
|
||||
__BOTTOM__
|
||||
} # print_bottom
|
||||
|
||||
|
||||
sub link_includes {
|
||||
local ($text) = $_[0];
|
||||
|
||||
if ($text =~ /\#(\s*)include(\s*)"(.*?)"/) {
|
||||
foreach $trial_root (($rcs_path, 'ns/include',
|
||||
"$rcs_path/Attic", "$rcs_path/..")) {
|
||||
if (-r "$root/$trial_root/$3,v") {
|
||||
$text = "$`#$1include$2\"<A HREF='cvsblame.cgi"
|
||||
."?root=$root&file=$trial_root/$3&rev=".$browse_revtag
|
||||
."&use_html=$use_html'>$3</A>\";$'";
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $text;
|
||||
}
|
||||
|
||||
sub html_comments_init {
|
||||
return 0 unless defined($form{'use_html'}) && $form{'use_html'};
|
||||
|
||||
# Initialization for C comment context switching
|
||||
$in_comments = 0;
|
||||
$open_delim = '\/\*';
|
||||
$close_delim = '\*\/';
|
||||
|
||||
# Initialize the next expected delim
|
||||
$expected_delim = $open_delim;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub leave_html_comments {
|
||||
local ($text) = $_[0];
|
||||
# Allow HTML in the comments.
|
||||
#
|
||||
$newtext = "";
|
||||
$oldtext = $text;
|
||||
while ($oldtext =~ /(.*$expected_delim)(.*\n)/) {
|
||||
$a = $1;
|
||||
$b = $2;
|
||||
# pay no attention to C++ comments within C comment context
|
||||
if ($in_comments == 0) {
|
||||
$a =~ s/</</g;
|
||||
$a =~ s/>/>/g;
|
||||
$expected_delim = $close_delim;
|
||||
$in_comments = 1;
|
||||
}
|
||||
else {
|
||||
$expected_delim = $open_delim;
|
||||
$in_comments = 0;
|
||||
}
|
||||
$newtext = $newtext . $a;
|
||||
$oldtext = $b;
|
||||
}
|
||||
# Handle thre remainder
|
||||
if ($in_comments == 0){
|
||||
$oldtext =~ s/</</g;
|
||||
$oldtext =~ s/>/>/g;
|
||||
}
|
||||
$text = $newtext . $oldtext;
|
||||
|
||||
# Now fix the breakage of <username> stuff on xfe. -byrd
|
||||
if ($text =~ /(.*)<(.*@.*)>(.*\n)/) {
|
||||
$text = $1 . "<A HREF=mailto:$2?subject=$filename>$2</A>" . $3;
|
||||
}
|
||||
|
||||
return $text;
|
||||
}
|
|
@ -0,0 +1,816 @@
|
|||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# cvsblame.pl - Shamelessly adapted from Scott Furman's cvsblame script
|
||||
# by Steve Lamm (slamm@netscape.com)
|
||||
# - Annotate each line of a CVS file with its author,
|
||||
# revision #, date, etc.
|
||||
#
|
||||
# Report problems to Steve Lamm (slamm@netscape.com)
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# $Id: cvsblame.pl,v 1.1 1998-06-16 21:42:56 terry Exp $
|
||||
|
||||
require 'timelocal.pl'; # timestamps
|
||||
require 'ctime.pl'; # human-readable dates
|
||||
|
||||
$debug = 0;
|
||||
|
||||
# Extract base part of this script's name
|
||||
($progname) = $0 =~ /([^\/]+)$/;
|
||||
|
||||
&cvsblame_init;
|
||||
|
||||
1;
|
||||
|
||||
sub cvsblame_init {
|
||||
# Use default formatting options if none supplied
|
||||
if (!$opt_A && !$opt_a && !$opt_d && !$opt_v) {
|
||||
$opt_a = 1;
|
||||
$opt_v = 1;
|
||||
}
|
||||
|
||||
$time = time;
|
||||
$SECS_PER_DAY = 60 * 60 * 24;
|
||||
|
||||
# Timestamp threshold at which annotations begin to occur, if -m option present.
|
||||
$opt_m_timestamp = $time - $opt_m * $SECS_PER_DAY;
|
||||
}
|
||||
|
||||
# Generic traversal of a CVS tree. Invoke callback function for
|
||||
# individual directories that contain CVS files.
|
||||
sub traverse_cvs_tree {
|
||||
local ($dir, *callback, $nlink) = @_;
|
||||
local ($dev, $ino, $mode, $subcount);
|
||||
|
||||
# Get $nlink for top-level directory
|
||||
($dev, $ino, $mode, $nlink) = stat($dir) unless $nlink;
|
||||
|
||||
# Read directory
|
||||
opendir(DIR, $dir) || die "Can't open $dir\n";
|
||||
local(@filenames) = readdir(DIR);
|
||||
closedir(DIR);
|
||||
|
||||
return if ! -d "$dir/CVS";
|
||||
|
||||
&callback($dir);
|
||||
|
||||
# This dir has subdirs
|
||||
if ($nlink != 2) {
|
||||
$subcount = $nlink - 2; # Number of subdirectories
|
||||
for (@filenames) {
|
||||
last if $subcount == 0;
|
||||
next if $_ eq '.';
|
||||
next if $_ eq '..';
|
||||
next if $_ eq 'CVS';
|
||||
$name = "$dir/$_";
|
||||
|
||||
($dev, $ino, $mode, $nlink) = lstat($name);
|
||||
next unless -d _;
|
||||
if (-x _ && -r _) {
|
||||
print STDERR "$progname: Entering $name\n";
|
||||
&traverse_cvs_tree($name, *callback, $nlink);
|
||||
} else {
|
||||
warn("Couldn't chdir to $name");
|
||||
}
|
||||
--$subcount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Consume one token from the already opened RCSFILE filehandle.
|
||||
# Unescape string tokens, if necessary.
|
||||
sub get_token {
|
||||
# Erase all-whitespace lines.
|
||||
while ($line_buffer =~ /^$/) {
|
||||
die ("Unexpected EOF") if eof(RCSFILE);
|
||||
$line_buffer = <RCSFILE>;
|
||||
$line_buffer =~ s/^\s+//; # Erase leading whitespace
|
||||
}
|
||||
|
||||
# A string of non-whitespace characters is a token ...
|
||||
return $1 if ($line_buffer =~ s/^([^;@][^;\s]*)\s*//o);
|
||||
|
||||
# ...and so is a single semicolon ...
|
||||
return ';' if ($line_buffer =~ s/^;\s*//o);
|
||||
|
||||
# ...or an RCS-encoded string that starts with an @ character.
|
||||
$line_buffer =~ s/^@([^@]*)//o;
|
||||
$token = $1;
|
||||
|
||||
# Detect single @ character used to close RCS-encoded string.
|
||||
while ($line_buffer !~ /@/o || # Short-circuit optimization
|
||||
$line_buffer !~ /([^@]|^)@([^@]|$)/o) {
|
||||
$token .= $line_buffer;
|
||||
die ("Unexpected EOF") if eof(RCSFILE);
|
||||
$line_buffer = <RCSFILE>;
|
||||
}
|
||||
|
||||
# Retain the remainder of the line after the terminating @ character.
|
||||
$i = rindex($line_buffer, '@');
|
||||
$token .= substr($line_buffer, 0, $i);
|
||||
$line_buffer = substr($line_buffer, $i + 1);
|
||||
|
||||
# Undo escape-coding of @ characters.
|
||||
$token =~ s/@@/@/og;
|
||||
|
||||
return $token;
|
||||
}
|
||||
|
||||
# Consume a token from RCS filehandle and ensure that it matches
|
||||
# the given string constant.
|
||||
sub match_token {
|
||||
local ($match) = @_;
|
||||
|
||||
local ($token) = &get_token;
|
||||
die "Unexpected parsing error in RCS file $rcs_pathname.\n",
|
||||
"Expected token: $match, but saw: $token\n"
|
||||
if ($token ne $match);
|
||||
}
|
||||
|
||||
# Push RCS token back into the input buffer.
|
||||
sub unget_token {
|
||||
local ($token) = @_;
|
||||
$line_buffer = $token . " " . $line_buffer;
|
||||
}
|
||||
|
||||
# Parses "administrative" header of RCS files, setting these globals:
|
||||
#
|
||||
# $head_revision -- Revision for which cleartext is stored
|
||||
# $principal_branch
|
||||
# $file_description
|
||||
# %revision_symbolic_name -- mapping from numerical revision # to symbolic tag
|
||||
# %tag_revision -- mapping from symbolic tag to numerical revision #
|
||||
#
|
||||
sub parse_rcs_admin {
|
||||
local ($token, $tag, $tag_name, $tag_revision);
|
||||
|
||||
# Undefine variables, because we may have already read another RCS file
|
||||
undef %tag_revision;
|
||||
undef %revision_symbolic_name;
|
||||
|
||||
while (1) {
|
||||
# Read initial token at beginning of line
|
||||
$token = &get_token(RCSFILE);
|
||||
|
||||
# We're done once we reach the description of the RCS tree
|
||||
if ($token =~ /^\d/o) {
|
||||
&unget_token($token);
|
||||
return;
|
||||
}
|
||||
|
||||
# print "token: $token\n";
|
||||
|
||||
if ($token eq "head") {
|
||||
$head_revision = &get_token;
|
||||
&get_token; # Eat semicolon
|
||||
} elsif ($token eq "branch") {
|
||||
$principal_branch = &get_token;
|
||||
&get_token; # Eat semicolon
|
||||
} elsif ($token eq "symbols") {
|
||||
|
||||
# Create an associate array that maps from tag name to
|
||||
# revision number and vice-versa.
|
||||
while (($tag = &get_token) ne ';') {
|
||||
($tag_name, $tag_revision) = split(':', $tag);
|
||||
|
||||
$tag_revision{$tag_name} = $tag_revision;
|
||||
$revision_symbolic_name{$tag_revision} = $tag_name;
|
||||
}
|
||||
} elsif ($token eq "comment") {
|
||||
$file_description = &get_token;
|
||||
&get_token; # Eat semicolon
|
||||
|
||||
# Ignore all these other fields - We don't care about them.
|
||||
} elsif (($token eq "locks") ||
|
||||
($token eq "strict") ||
|
||||
($token eq "expand") ||
|
||||
($token eq "access")) {
|
||||
(1) while (&get_token ne ';');
|
||||
} else {
|
||||
warn ("Unexpected RCS token: $token\n");
|
||||
}
|
||||
}
|
||||
|
||||
die "Unexpected EOF";
|
||||
}
|
||||
|
||||
# Construct associative arrays that represent the topology of the RCS tree
|
||||
# and other arrays that contain info about individual revisions.
|
||||
#
|
||||
# The following associative arrays are created, keyed by revision number:
|
||||
# %revision_date -- e.g. "96.02.23.00.21.52"
|
||||
# %timestamp -- seconds since 12:00 AM, Jan 1, 1970 GMT
|
||||
# %revision_author -- e.g. "tom"
|
||||
# %revision_branches -- descendant branch revisions, separated by spaces,
|
||||
# e.g. "1.21.4.1 1.21.2.6.1"
|
||||
# %prev_revision -- revision number of previous *ancestor* in RCS tree.
|
||||
# Traversal of this array occurs in the direction
|
||||
# of the primordial (1.1) revision.
|
||||
# %prev_delta -- revision number of previous revision which forms the
|
||||
# basis for the edit commands in this revision.
|
||||
# This causes the tree to be traversed towards the
|
||||
# trunk when on a branch, and towards the latest trunk
|
||||
# revision when on the trunk.
|
||||
# %next_delta -- revision number of next "delta". Inverts %prev_delta.
|
||||
#
|
||||
# Also creates %last_revision, keyed by a branch revision number, which
|
||||
# indicates the latest revision on a given branch,
|
||||
# e.g. $last_revision{"1.2.8"} == 1.2.8.5
|
||||
#
|
||||
sub parse_rcs_tree {
|
||||
local($revision, $date, $author, $branches, $next);
|
||||
local($branch, $is_trunk_revision);
|
||||
local($mon,$day,$hhmm,$year);
|
||||
# Undefine variables, because we may have already read another RCS file
|
||||
undef %timestamp;
|
||||
undef %revision_age;
|
||||
undef %revision_author;
|
||||
undef %revision_branches;
|
||||
undef %revision_ctime;
|
||||
undef %revision_date;
|
||||
undef %prev_revision;
|
||||
undef %prev_delta;
|
||||
undef %next_delta;
|
||||
undef %last_revision;
|
||||
|
||||
while (1) {
|
||||
$revision = &get_token;
|
||||
|
||||
# End of RCS tree description ?
|
||||
if ($revision eq 'desc') {
|
||||
&unget_token($revision);
|
||||
return;
|
||||
}
|
||||
|
||||
$is_trunk_revision = ($revision =~ /^[0-9]+\.[0-9]+$/);
|
||||
|
||||
$tag_revision{$revision} = $revision;
|
||||
($branch) = $revision =~ /(.*)\.[0-9]+/o;
|
||||
$last_revision{$branch} = $revision;
|
||||
|
||||
# Parse date
|
||||
&match_token('date');
|
||||
$date = &get_token;
|
||||
$revision_date{$revision} = $date;
|
||||
&match_token(';');
|
||||
|
||||
# Convert date into timestamp
|
||||
@date_fields = reverse(split(/\./, $date));
|
||||
$date_fields[4]--; # Month ranges from 0-11, not 1-12
|
||||
$timestamp{$revision} = &timegm(@date_fields);
|
||||
|
||||
# Compute date string; Format it the way I like.
|
||||
($mon, $day, $hhmm, $year)
|
||||
= &ctime($timestamp{$revision})
|
||||
=~ /... (...) (..) (..:..):.. \S* (....)/;
|
||||
$revision_ctime{$revision} = "$day $mon $year $hhmm";
|
||||
# $revision_ctime{$revision} = &ctime($timestamp{$revision});
|
||||
|
||||
# Save age
|
||||
$revision_age{$revision} =
|
||||
($time - $timestamp{$revision}) / $SECS_PER_DAY;
|
||||
|
||||
# Parse author
|
||||
&match_token('author');
|
||||
$author = &get_token;
|
||||
$revision_author{$revision} = $author;
|
||||
&match_token(';');
|
||||
|
||||
# Parse state;
|
||||
&match_token('state');
|
||||
(1) while (&get_token ne ';');
|
||||
|
||||
# Parse branches
|
||||
&match_token('branches');
|
||||
$branches = '';
|
||||
while (($token = &get_token) ne ';') {
|
||||
$prev_revision{$token} = $revision;
|
||||
$prev_delta{$token} = $revision;
|
||||
$branches .= "$token ";
|
||||
}
|
||||
$revision_branches{$revision} = $branches;
|
||||
|
||||
# Parse revision of next delta in chain
|
||||
&match_token('next');
|
||||
$next = '';
|
||||
if (($token = &get_token) ne ';') {
|
||||
$next = $token;
|
||||
&get_token; # Eat semicolon
|
||||
$next_delta{$revision} = $next;
|
||||
$prev_delta{$next} = $revision;
|
||||
if ($is_trunk_revision) {
|
||||
$prev_revision{$revision} = $next;
|
||||
} else {
|
||||
$prev_revision{$next} = $revision;
|
||||
}
|
||||
}
|
||||
|
||||
if ($debug >= 3) {
|
||||
print "<pre>revision = $revision\n";
|
||||
print "date = $date\n";
|
||||
print "author = $author\n";
|
||||
print "branches = $branches\n";
|
||||
print "next = $next</pre>\n\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub parse_rcs_description {
|
||||
&match_token('desc');
|
||||
$rcs_file_description = &get_token;
|
||||
}
|
||||
|
||||
# Construct associative arrays containing info about individual revisions.
|
||||
#
|
||||
# The following associative arrays are created, keyed by revision number:
|
||||
# %revision_log -- log message
|
||||
# %revision_deltatext -- Either the complete text of the revision,
|
||||
# in the case of the head revision, or the
|
||||
# encoded delta between this revision and another.
|
||||
# The delta is either with respect to the successor
|
||||
# revision if this revision is on the trunk or
|
||||
# relative to its immediate predecessor if this
|
||||
# revision is on a branch.
|
||||
sub parse_rcs_deltatext {
|
||||
undef %revision_log;
|
||||
undef %revision_deltatext;
|
||||
|
||||
while (!eof(RCSFILE)) {
|
||||
$revision = &get_token;
|
||||
print "Reading delta for revision: $revision\n" if ($debug >= 3);
|
||||
&match_token('log');
|
||||
$revision_log{$revision} = &get_token;
|
||||
&match_token('text');
|
||||
$revision_deltatext{$revision} = &get_token;
|
||||
}
|
||||
}
|
||||
|
||||
# Reads and parses complete RCS file from already-opened RCSFILE descriptor.
|
||||
sub parse_rcs_file {
|
||||
print "Reading RCS admin...\n" if ($debug >= 2);
|
||||
&parse_rcs_admin();
|
||||
print "Reading RCS revision tree topology...\n" if ($debug >= 2);
|
||||
&parse_rcs_tree();
|
||||
|
||||
if( $debug >= 3 ){
|
||||
print "<pre>Keys:\n\n";
|
||||
for $i (keys %tag_revision ){
|
||||
$k = $tag_revision{$i};
|
||||
print "yoyuo $i: $k\n";
|
||||
}
|
||||
print "</pre>\n";
|
||||
}
|
||||
|
||||
&parse_rcs_description();
|
||||
print "Reading RCS revision deltas...\n" if ($debug >= 2);
|
||||
&parse_rcs_deltatext();
|
||||
print "Done reading RCS file...\n" if ($debug >= 2);
|
||||
}
|
||||
|
||||
# Map a tag to a numerical revision number. The tag can be a symbolic
|
||||
# branch tag, a symbolic revision tag, or an ordinary numerical
|
||||
# revision number.
|
||||
sub map_tag_to_revision {
|
||||
local($tag_or_revision) = @_;
|
||||
|
||||
local ($revision) = $tag_revision{$tag_or_revision};
|
||||
|
||||
# Is this a branch tag, e.g. xxx.yyy.0.zzz
|
||||
if ($revision =~ /(.*)\.0\.([0-9]+)/o) {
|
||||
$branch = $1 . '.' . $2;
|
||||
# Return latest revision on the branch, if any.
|
||||
return $last_revision{$branch} if (defined($last_revision{$branch}));
|
||||
return $1; # No revisions on branch - return branch point
|
||||
} else {
|
||||
return $revision;
|
||||
}
|
||||
}
|
||||
|
||||
# Construct an ordered list of ancestor revisions to the given
|
||||
# revision, starting with the immediate ancestor and going back
|
||||
# to the primordial revision (1.1).
|
||||
#
|
||||
# Note: The generated path does not traverse the tree the same way
|
||||
# that the individual revision deltas do. In particular,
|
||||
# the path traverses the tree "backwards" on branches.
|
||||
|
||||
sub ancestor_revisions {
|
||||
local ($revision) = @_;
|
||||
local (@ancestors);
|
||||
|
||||
$revision = $prev_revision{$revision};
|
||||
while ($revision) {
|
||||
push(@ancestors, $revision);
|
||||
$revision = $prev_revision{$revision};
|
||||
}
|
||||
|
||||
return @ancestors;
|
||||
}
|
||||
|
||||
# Extract the given revision from the digested RCS file.
|
||||
# (Essentially the equivalent of cvs up -rXXX)
|
||||
sub extract_revision {
|
||||
local ($revision) = @_;
|
||||
local (@path);
|
||||
|
||||
# Compute path through tree of revision deltas to most recent trunk revision
|
||||
while ($revision) {
|
||||
push(@path, $revision);
|
||||
$revision = $prev_delta{$revision};
|
||||
}
|
||||
@path = reverse(@path);
|
||||
shift @path; # Get rid of head revision
|
||||
|
||||
# Get complete contents of head revision
|
||||
local (@text) = split(/^/, $revision_deltatext{$head_revision});
|
||||
|
||||
# Iterate, applying deltas to previous revision
|
||||
foreach $revision (@path) {
|
||||
$adjust = 0;
|
||||
@diffs = split(/^/, $revision_deltatext{$revision});
|
||||
|
||||
local ($lines_added) = 0;
|
||||
local ($lines_removed) = 0;
|
||||
|
||||
foreach $command (@diffs) {
|
||||
if ($add_lines_remaining > 0) {
|
||||
# Insertion lines from a prior "a" command.
|
||||
splice(@text, $start_line + $adjust,
|
||||
0, $command);
|
||||
$add_lines_remaining--;
|
||||
$adjust++;
|
||||
} elsif ($command =~ /^d(\d+)\s(\d+)/) {
|
||||
# "d" - Delete command
|
||||
($start_line, $count) = ($1, $2);
|
||||
splice(@text, $start_line + $adjust - 1, $count);
|
||||
$adjust -= $count;
|
||||
$lines_removed += $count;
|
||||
} elsif ($command =~ /^a(\d+)\s(\d+)/) {
|
||||
# "a" - Add command
|
||||
($start_line, $count) = ($1, $2);
|
||||
$add_lines_remaining = $count;
|
||||
$lines_added += $lines_added;
|
||||
} else {
|
||||
die "Error parsing diff commands";
|
||||
}
|
||||
}
|
||||
$lines_removed{$revision} += $lines_removed;
|
||||
$lines_added{$revision} += $lines_added;
|
||||
}
|
||||
|
||||
return @text;
|
||||
}
|
||||
|
||||
sub parse_cvs_file {
|
||||
local($rcs_pathname) = @_;
|
||||
|
||||
# Args in: $opt_rev - requested revision
|
||||
# $opt_m - time since modified
|
||||
# Args out: @revision_map
|
||||
# $revision
|
||||
# %timestamp
|
||||
# (%revision_deltatext)
|
||||
|
||||
@revision_map = ();
|
||||
die "$progname: error: This file appeared to be under CVS control, " .
|
||||
"but the RCS file is inaccessible.\n(Couldn't open '$rcs_pathname')\n"
|
||||
if !open (RCSFILE, "< $rcs_pathname");
|
||||
&parse_rcs_file();
|
||||
close(RCSFILE);
|
||||
|
||||
if (!defined($opt_rev) || $opt_rev eq '' || $opt_rev eq 'HEAD') {
|
||||
# Explicitly specified topmost revision in tree
|
||||
$revision = $head_revision;
|
||||
} else {
|
||||
# Symbolic tag or specific revision number specified.
|
||||
$revision = &map_tag_to_revision($opt_rev);
|
||||
die "$progname: error: -r: No such revision: $opt_rev\n"
|
||||
if ($revision eq '');
|
||||
}
|
||||
|
||||
# The primordial revision is not always 1.1! Go find it.
|
||||
my $primordial = $revision;
|
||||
while ($prev_revision{$primordial} != "") {
|
||||
$primordial = $prev_revision{$primordial};
|
||||
}
|
||||
|
||||
# Don't display file at all, if -m option is specified and no
|
||||
# changes have been made in the specified file.
|
||||
return if ($opt_m && $timestamp{$revision} < $opt_m_timestamp);
|
||||
|
||||
# Figure out how many lines were in the primordial, i.e. version 1.1,
|
||||
# check-in by moving backward in time from the head revision to the
|
||||
# first revision.
|
||||
$line_count = split(/^/, $revision_deltatext{$head_revision});
|
||||
for ($rev = $prev_revision{$head_revision}; $rev;
|
||||
$rev = $prev_revision{$rev}) {
|
||||
@diffs = split(/^/, $revision_deltatext{$rev});
|
||||
foreach $command (@diffs) {
|
||||
if ($skip > 0) {
|
||||
# Skip insertion lines from a prior "a" command.
|
||||
$skip--;
|
||||
} elsif ($command =~ /^d(\d+)\s(\d+)/) {
|
||||
# "d" - Delete command
|
||||
($start_line, $count) = ($1, $2);
|
||||
$line_count -= $count;
|
||||
} elsif ($command =~ /^a(\d+)\s(\d+)/) {
|
||||
# "a" - Add command
|
||||
($start_line, $count) = ($1, $2);
|
||||
$skip = $count;
|
||||
$line_count += $count;
|
||||
} else {
|
||||
die "$progname: error: illegal RCS file $rcs_pathname\n",
|
||||
" error appears in revision $rev\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Now, play the delta edit commands *backwards* from the primordial
|
||||
# revision forward, but rather than applying the deltas to the text of
|
||||
# each revision, apply the changes to an array of revision numbers.
|
||||
# This creates a "revision map" -- an array where each element
|
||||
# represents a line of text in the given revision but contains only
|
||||
# the revision number in which the line was introduced rather than
|
||||
# the line text itself.
|
||||
#
|
||||
# Note: These are backward deltas for revisions on the trunk and
|
||||
# forward deltas for branch revisions.
|
||||
|
||||
# Create initial revision map for primordial version.
|
||||
while ($line_count--) {
|
||||
push(@revision_map, $primordial);
|
||||
}
|
||||
|
||||
@ancestors = &ancestor_revisions($revision);
|
||||
unshift (@ancestors, $revision); #
|
||||
pop @ancestors; # Remove "1.1"
|
||||
$last_revision = $primordial;
|
||||
foreach $revision (reverse @ancestors) {
|
||||
$is_trunk_revision = ($revision =~ /^[0-9]+\.[0-9]+$/);
|
||||
|
||||
if ($is_trunk_revision) {
|
||||
@diffs = split(/^/, $revision_deltatext{$last_revision});
|
||||
|
||||
# Revisions on the trunk specify deltas that transform a
|
||||
# revision into an earlier revision, so invert the translation
|
||||
# of the 'diff' commands.
|
||||
foreach $command (@diffs) {
|
||||
if ($skip > 0) {
|
||||
$skip--;
|
||||
} else {
|
||||
if ($command =~ /^d(\d+)\s(\d+)$/) { # Delete command
|
||||
($start_line, $count) = ($1, $2);
|
||||
|
||||
$#temp = -1;
|
||||
while ($count--) {
|
||||
push(@temp, $revision);
|
||||
}
|
||||
splice(@revision_map, $start_line - 1, 0, @temp);
|
||||
} elsif ($command =~ /^a(\d+)\s(\d+)$/) { # Add command
|
||||
($start_line, $count) = ($1, $2);
|
||||
splice(@revision_map, $start_line, $count);
|
||||
$skip = $count;
|
||||
} else {
|
||||
die "Error parsing diff commands";
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
# Revisions on a branch are arranged backwards from those on
|
||||
# the trunk. They specify deltas that transform a revision
|
||||
# into a later revision.
|
||||
$adjust = 0;
|
||||
@diffs = split(/^/, $revision_deltatext{$revision});
|
||||
foreach $command (@diffs) {
|
||||
if ($skip > 0) {
|
||||
$skip--;
|
||||
} else {
|
||||
if ($command =~ /^d(\d+)\s(\d+)$/) { # Delete command
|
||||
($start_line, $count) = ($1, $2);
|
||||
splice(@revision_map, $start_line + $adjust - 1, $count);
|
||||
$adjust -= $count;
|
||||
} elsif ($command =~ /^a(\d+)\s(\d+)$/) { # Add command
|
||||
($start_line, $count) = ($1, $2);
|
||||
|
||||
$skip = $count;
|
||||
$#temp = -1;
|
||||
while ($count--) {
|
||||
push(@temp, $revision);
|
||||
}
|
||||
splice(@revision_map, $start_line + $adjust, 0, @temp);
|
||||
$adjust += $skip;
|
||||
} else {
|
||||
die "Error parsing diff commands";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$last_revision = $revision;
|
||||
}
|
||||
$revision;
|
||||
}
|
||||
|
||||
__END__
|
||||
#
|
||||
# The following are parts of the original cvsblame script that are not
|
||||
# used for cvsblame.pl
|
||||
#
|
||||
|
||||
# Read CVS/Entries and CVS/Repository files.
|
||||
#
|
||||
# Creates these associative arrays, keyed by the CVS file pathname
|
||||
#
|
||||
# %cvs_revision -- Revision # present in working directory
|
||||
# %cvs_date
|
||||
# %cvs_sticky_revision -- Sticky tag, if any
|
||||
#
|
||||
# Also, creates %cvs_files, keyed by the directory path, which contains
|
||||
# a space-separated list of the files under CVS control in the directory
|
||||
sub read_cvs_entries
|
||||
{
|
||||
local ($directory) = @_;
|
||||
local ($filename, $rev, $date, $idunno, $sticky, $pathname);
|
||||
|
||||
$cvsdir = $directory . '/CVS';
|
||||
|
||||
return if (! -d $cvsdir);
|
||||
|
||||
return if !open(ENTRIES, "< $cvsdir/Entries");
|
||||
|
||||
while(<ENTRIES>) {
|
||||
chop;
|
||||
($filename, $rev, $date, $idunno, $sticky) = split("/", substr($_, 1));
|
||||
($pathname) = $directory . "/" . $filename;
|
||||
$cvs_revision{$pathname} = $rev;
|
||||
$cvs_date{$pathname} = $date;
|
||||
$cvs_sticky_revision{$pathname} = $sticky;
|
||||
$cvs_files{$directory} .= "$filename\\";
|
||||
}
|
||||
close(ENTRIES);
|
||||
|
||||
return if !open(REPOSITORY, "< $cvsdir/Repository");
|
||||
$repository = <REPOSITORY>;
|
||||
chop($repository);
|
||||
close(REPOSITORY);
|
||||
$repository{$directory} = $repository;
|
||||
}
|
||||
|
||||
# Given path to file in CVS working directory, compute path to RCS
|
||||
# repository file. Cache that info for future use.
|
||||
sub rcs_pathname {
|
||||
($pathname) = @_;
|
||||
|
||||
if ($pathname =~ m@/@) {
|
||||
($directory,$filename) = $pathname =~ m@(.*)/([^/]+)$@;
|
||||
} else {
|
||||
($directory,$filename) = ('.',$pathname);
|
||||
$pathname = "./" . $pathname;
|
||||
}
|
||||
if (!defined($repository{$directory})) {
|
||||
&read_cvs_entries($directory);
|
||||
}
|
||||
|
||||
if (!defined($cvs_revision{$pathname})) {
|
||||
die "$progname: error: File '$pathname' does not appear to be under" .
|
||||
" CVS control.\n"
|
||||
}
|
||||
|
||||
print STDERR "file: $filename\n" if $debug;
|
||||
local ($rcs_path) = $repository{$directory} . '/' . $filename . ',v';
|
||||
return $rcs_path if (-r $rcs_path);
|
||||
|
||||
# A file that exists only on the branch, not on the trunk, is found
|
||||
# in the Attic subdir.
|
||||
return $repository{$directory} . '/Attic/' . $filename . ',v';
|
||||
}
|
||||
|
||||
sub show_annotated_cvs_file {
|
||||
local($pathname) = @_;
|
||||
local(@output) = ();
|
||||
|
||||
$revision = &parse_cvs_file($pathname);
|
||||
|
||||
@text = &extract_revision($revision);
|
||||
die "$progname: Internal consistency error" if ($#text != $#revision_map);
|
||||
|
||||
# Set total width of line annotation.
|
||||
# Warning: field widths here must match format strings below.
|
||||
$annotation_width = 0;
|
||||
$annotation_width += 8 if $opt_a; # author
|
||||
$annotation_width += 7 if $opt_v; # revision
|
||||
$annotation_width += 6 if $opt_A; # age
|
||||
$annotation_width += 12 if $opt_d; # date
|
||||
$blank_annotation = ' ' x $annotation_width;
|
||||
|
||||
if ($multiple_files_on_command_line) {
|
||||
print "\n", "=" x (83 + $annotation_width);
|
||||
print "\n$progname: Listing file: $pathname\n"
|
||||
}
|
||||
|
||||
# Print each line of the revision, preceded by its annotation.
|
||||
$line = 0;
|
||||
foreach $revision (@revision_map) {
|
||||
$text = $text[$line++];
|
||||
$annotation = '';
|
||||
|
||||
# Annotate with revision author
|
||||
$annotation .= sprintf("%-8s", $revision_author{$revision}) if $opt_a;
|
||||
|
||||
# Annotate with revision number
|
||||
$annotation .= sprintf(" %-6s", $revision) if $opt_v;
|
||||
|
||||
# Date annotation
|
||||
$annotation .= " $revision_ctime{$revision}" if $opt_d;
|
||||
|
||||
# Age annotation ?
|
||||
$annotation .= sprintf(" (%3s)",
|
||||
int($revision_age{$revision})) if $opt_A;
|
||||
|
||||
# -m (if-modified-since) annotion ?
|
||||
if ($opt_m && ($timestamp{$revision} < $opt_m_timestamp)) {
|
||||
$annotation = $blank_annotation;
|
||||
}
|
||||
|
||||
# Suppress annotation of whitespace lines, if requested;
|
||||
$annotation = $blank_annotation if $opt_w && ($text =~ /^\s*$/);
|
||||
|
||||
# printf "%4d ", $line if $opt_l;
|
||||
# print "$annotation - $text";
|
||||
push(@output, sprintf("%4d ", $line)) if $opt_l;
|
||||
push(@output, "$annotation - $text");
|
||||
}
|
||||
@output;
|
||||
}
|
||||
|
||||
sub usage {
|
||||
die
|
||||
"$progname: usage: [options] [file|dir]...\n",
|
||||
" Options:\n",
|
||||
" -r <revision> Specify CVS revision of file to display\n",
|
||||
" <revision> can be any of:\n",
|
||||
" + numeric tag, e.g. 1.23,\n",
|
||||
" + symbolic branch or revision tag, e.g. CHEDDAR,\n",
|
||||
" + HEAD keyword (most recent revision on trunk)\n",
|
||||
" -a Annotate lines with author (username)\n",
|
||||
" -A Annotate lines with age, in days\n",
|
||||
" -v Annotate lines with revision number\n",
|
||||
" -d Annotate lines with date, in local time zone\n",
|
||||
" -l Annotate lines with line number\n",
|
||||
" -w Don't annotate all-whitespace lines\n",
|
||||
" -m <# days> Only annotate lines modified within last <# days>\n",
|
||||
" -h Print help (this message)\n\n",
|
||||
" (-a -v assumed, if none of -a, -v, -A, -d supplied)\n"
|
||||
;
|
||||
}
|
||||
|
||||
&usage if (!&Getopts('r:m:Aadhlvw'));
|
||||
&usage if ($opt_h); # help option
|
||||
|
||||
$multiple_files_on_command_line = 1 if ($#ARGV != 0);
|
||||
|
||||
&cvsblame_init;
|
||||
|
||||
sub annotate_cvs_directory
|
||||
{
|
||||
local($dir) = @_;
|
||||
&read_cvs_entries($dir);
|
||||
foreach $file (split(/\\/, $cvs_files{$dir})) {
|
||||
&show_annotated_cvs_file("$dir/$file");
|
||||
}
|
||||
}
|
||||
|
||||
# No files on command-line ? Use current directory.
|
||||
push(@ARGV, '.') if ($#ARGV == -1);
|
||||
|
||||
# Iterate over files/directories on command-line
|
||||
while ($#ARGV >= 0) {
|
||||
$pathname = shift @ARGV;
|
||||
# Is it a directory ?
|
||||
if (-d $pathname) {
|
||||
&traverse_cvs_tree($pathname, *annotate_cvs_directory);
|
||||
|
||||
# No, it must be a file.
|
||||
} else {
|
||||
&show_annotated_cvs_file($pathname);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
require 'lloydcgi.pl';
|
||||
require 'utils.pl';
|
||||
|
||||
$file= $form{'file'};
|
||||
$mark= $form{'mark'};
|
||||
$ln = ($mark > 10 ? $mark-10 : 1 );
|
||||
$rev = $form{'rev'};
|
||||
$debug = $form{'debug'};
|
||||
|
||||
print "Content-Type: text/html\n\n";
|
||||
|
||||
$CVS_ROOT = $form{'root'};
|
||||
if( $CVS_ROOT eq '' ){
|
||||
$CVS_ROOT = pickDefaultRepository();
|
||||
}
|
||||
validateRepository($CVS_ROOT);
|
||||
|
||||
$CVS_REPOS_SUFIX = $CVS_ROOT;
|
||||
$CVS_REPOS_SUFIX =~ s/\//_/g;
|
||||
|
||||
$db = ConnectToDatabase();
|
||||
|
||||
$f = SqlQuote($file);
|
||||
$qstring = "select distinct dirs.dir from checkins,dirs,files,repositories where dirs.id=dirid and files.id=fileid and repositories.id=repositoryid and repositories.repository='$CVS_ROOT' and files.file='$f' order by dirs.dir";
|
||||
|
||||
if ($debug) {
|
||||
print "<pre wrap>$qstring</pre>\n";
|
||||
}
|
||||
|
||||
$query = $db->Query($qstring) || die $Mysql::db_errstr;
|
||||
|
||||
while(@row = $query->fetchrow){
|
||||
$d = $row[0];
|
||||
push @fl, "$d/$file";
|
||||
}
|
||||
|
||||
if( @fl == 0 ){
|
||||
print "<h3>No files matched this file name. It may have been added recently.</h3>";
|
||||
}
|
||||
elsif( @fl == 1 ){
|
||||
$s = $fl[0];
|
||||
print "<head>
|
||||
<meta http-equiv=Refresh
|
||||
content=\"0; URL=cvsblame.cgi?file=$s&rev=$rev&root=$CVS_ROOT&mark=$mark#$ln\">
|
||||
</head>
|
||||
";
|
||||
}
|
||||
else {
|
||||
print "<h3>Pick the file that best matches the one you are looking for:</h3>\n";
|
||||
for $s (@fl) {
|
||||
print "<dt><a href=cvsblame.cgi?file=$s&rev=$rev&mark=$mark#$ln>$s</a>";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
|
||||
# Figure out which directory bonsai is in by looking at argv[0]
|
||||
|
||||
$bonsaidir = $0;
|
||||
$bonsaidir =~ s:/[^/]*$::; # Remove last word, and slash before it.
|
||||
if ($bonsaidir eq "") {
|
||||
$bonsaidir = ".";
|
||||
}
|
||||
|
||||
chdir $bonsaidir || die "Couldn't chdir to $bonsaidir";
|
||||
require "utils.pl";
|
||||
|
||||
if( $ARGV[0] eq '' ){
|
||||
$CVS_ROOT = pickDefaultRepository();
|
||||
}
|
||||
else {
|
||||
$CVS_ROOT = $ARGV[0];
|
||||
}
|
||||
|
||||
$CVS_REPOS_SUFIX = $CVS_ROOT;
|
||||
$CVS_REPOS_SUFIX =~ s:/:_:g;
|
||||
|
||||
|
||||
$CHECKIN_DATA_FILE = "$bonsaidir/data/checkinlog${CVS_REPOS_SUFIX}";
|
||||
$CHECKIN_INDEX_FILE = "$bonsaidir/data/index${CVS_REPOS_SUFIX}";
|
||||
|
||||
&build_index;
|
||||
&print_keys;
|
||||
|
||||
sub build_index {
|
||||
open(CI, "<$CHECKIN_DATA_FILE") || die "could not open checkin data file\n";
|
||||
|
||||
$file_pos = 0;
|
||||
$lastlog = 0;
|
||||
$last_date = 0;
|
||||
$index = {};
|
||||
$now = time;
|
||||
while( <CI> ){
|
||||
if( /^LOGCOMMENT/ ){
|
||||
$done = 0;
|
||||
$file_pos += length;
|
||||
while( !$done && ($line = <CI>) ){
|
||||
if( $line =~ /^:ENDLOGCOMMENT/ ){
|
||||
$done = 1;
|
||||
}
|
||||
$file_pos += length($line);
|
||||
}
|
||||
}
|
||||
else {
|
||||
#print $_ . "\n";
|
||||
$ci = [split(/\|/)];
|
||||
$d = $ci->[1];
|
||||
|
||||
if( $d < $now && $d > ($last_date + 60*60*4) ){
|
||||
$index->{$d} = $file_pos;
|
||||
$last_date = $d;
|
||||
}
|
||||
$file_pos += length;
|
||||
}
|
||||
}
|
||||
close( CI );
|
||||
}
|
||||
|
||||
sub print_keys {
|
||||
Lock();
|
||||
open(INDEX , ">$CHECKIN_INDEX_FILE");
|
||||
for $i (sort {$b <=> $a} keys %{$index}) {
|
||||
print INDEX "$index->{$i}|$i\n";
|
||||
}
|
||||
close(INDEX);
|
||||
Unlock();
|
||||
}
|
|
@ -0,0 +1,493 @@
|
|||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
# cvslog.cgi -- cvslog with logs as popups and allowing html in comments.
|
||||
#
|
||||
# Created: Steve Lamm <slamm@netscape.com>, 31-Mar-98.
|
||||
#
|
||||
# Arguments (passed via GET or POST):
|
||||
# file - path to file name (e.g. ns/cmd/xfe/Makefile)
|
||||
# root - cvs root (e.g. /warp/webroot)
|
||||
# rev - revision (default is the latest version)
|
||||
# mark - highlight a revision
|
||||
# author - filter based on author
|
||||
#
|
||||
|
||||
require 'lloydcgi.pl';
|
||||
require 'cvsblame.pl';
|
||||
require 'utils.pl';
|
||||
use SourceChecker;
|
||||
|
||||
# Some Globals
|
||||
#
|
||||
|
||||
$| = 1;
|
||||
|
||||
print "Content-Type:text/html\n\n";
|
||||
|
||||
@src_roots = getRepositoryList();
|
||||
|
||||
|
||||
# Handle the "file" argument
|
||||
#
|
||||
$filename = '';
|
||||
$filename = $form{'file'} if defined($form{'file'});
|
||||
if ($filename eq '')
|
||||
{
|
||||
&print_usage;
|
||||
exit;
|
||||
}
|
||||
($file_head, $file_tail) = $filename =~ m@(.*/)?(.+)@;
|
||||
|
||||
|
||||
# Handle the "rev" argument
|
||||
#
|
||||
$opt_rev = $form{'rev'} if defined($form{'rev'} && $form{'rev'} ne 'HEAD');
|
||||
$browse_revtag = 'HEAD';
|
||||
$browse_revtag = $opt_rev if ($opt_rev =~ /[A-Za-z]/);
|
||||
$revision = '';
|
||||
|
||||
|
||||
# Handle the "root" argument
|
||||
#
|
||||
if (defined($root = $form{'root'}) && $root ne '') {
|
||||
$root =~ s|/$||;
|
||||
validateRepository($root);
|
||||
if (-d $root) {
|
||||
unshift(@src_roots, $root);
|
||||
} else {
|
||||
&print_top;
|
||||
print "Error: Root, $root, is not a directory.<BR><BR>\n";
|
||||
print "</BODY></HTML>\n";
|
||||
&print_bottom;
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
# Find the rcs file
|
||||
#
|
||||
foreach (@src_roots) {
|
||||
$root = $_;
|
||||
$rcs_filename = "$root/$filename,v";
|
||||
goto found_file if -r $rcs_filename;
|
||||
$rcs_filename = "$root/${file_head}Attic/$file_tail,v";
|
||||
goto found_file if -r $rcs_filename;
|
||||
}
|
||||
# File not found
|
||||
&print_top;
|
||||
print "Rcs file, $filename, does not exist.<BR><BR>\n";
|
||||
print "</BODY></HTML>\n";
|
||||
&print_bottom;
|
||||
exit;
|
||||
|
||||
found_file:
|
||||
($rcs_path) = $rcs_filename =~ m@$root/(.*)/.+?,v@;
|
||||
|
||||
|
||||
# Parse the rcs file ($opt_rev is passed as a global)
|
||||
#
|
||||
$revision = &parse_cvs_file($rcs_filename);
|
||||
$file_rev = $revision;
|
||||
|
||||
|
||||
# Handle the "mark" argument
|
||||
#
|
||||
$mark_arg = '';
|
||||
$mark_arg = $form{'mark'} if defined($form{'mark'});
|
||||
foreach $rev (split(',',$mark_arg)) {
|
||||
$mark{$rev} = 1;
|
||||
}
|
||||
|
||||
|
||||
# Handle the "author" argument
|
||||
#
|
||||
$author_arg = '';
|
||||
$author_arg = $form{'author'} if defined($form{'author'});
|
||||
foreach $author (split(',',$author_arg)) {
|
||||
$use_author{$author} = 1;
|
||||
}
|
||||
|
||||
|
||||
# Handle the "sort" argument
|
||||
$opt_sort = '';
|
||||
$opt_sort = $form{'sort'};
|
||||
|
||||
|
||||
# Start printing out the page
|
||||
#
|
||||
&print_top;
|
||||
|
||||
if ($ENV{'HTTP_USER_AGENT'} =~ /Win/) {
|
||||
$font_tag = "<FONT FACE='Lucida Console' SIZE=-1>";
|
||||
} else {
|
||||
# We don't want your stinking Windows font
|
||||
$font_tag = "<FONT>";
|
||||
}
|
||||
|
||||
# Print link at top for directory browsing
|
||||
#
|
||||
$output = "<DIV ALIGN=LEFT>";
|
||||
|
||||
foreach $path (split('/',$rcs_path)) {
|
||||
$link_path .= $path;
|
||||
$output .= "<A HREF='rview.cgi?dir=$link_path";
|
||||
$output .= "&cvsroot=$form{'root'}" if defined $form{'root'};
|
||||
$output .= "&rev=$browse_revtag" unless $browse_revtag eq 'HEAD';
|
||||
$output .= "' onmouseover='window.status=\"Browse $link_path\";"
|
||||
." return true;'>$path</A>/ ";
|
||||
$link_path .= '/';
|
||||
}
|
||||
$output .= "$file_tail (";
|
||||
$output .= "$browse_revtag:" unless $browse_revtag eq 'HEAD';
|
||||
$output .= $revision if $revision;
|
||||
$output .= ")";
|
||||
|
||||
EmitHtmlHeader("CVS Log", $output);
|
||||
|
||||
&print_useful_links($filename);
|
||||
|
||||
# Create a table with header links to sort by column.
|
||||
#
|
||||
$table_tag = "<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH='100%'>";
|
||||
if ($opt_sort eq 'author') {
|
||||
$table_header_tag .= "<TH ALIGN=LEFT><A HREF='cvslog.cgi?file=$filename&root=$root&rev=$browse_revtag&sort=revision&author=$author_arg'>Rev</A><TH ALIGN=LEFT>Author<TH ALIGN=LEFT><A HREF='cvslog.cgi?file=$filename&root=$root&rev=$browse_revtag&sort=date&author=$author_arg'>Date</A><TH><TH ALIGN=LEFT>Log";
|
||||
} else {
|
||||
$table_header_tag .= "<TH ALIGN=LEFT>Rev<TH ALIGN=LEFT><A HREF='cvslog.cgi?file=$filename&root=$root&rev=$browse_revtag&sort=author&author=$author_arg'>Author</A><TH ALIGN=LEFT>Date<TH><TH ALIGN=LEFT>Log";
|
||||
}
|
||||
|
||||
print "$font_tag$table_tag$table_header_tag";
|
||||
|
||||
# Print each line of the revision, preceded by its annotation.
|
||||
#
|
||||
if ($browse_revtag eq 'HEAD') {
|
||||
$start_rev = $head_revision; # $head_revision is a global from cvsblame.pl
|
||||
} else {
|
||||
$start_rev = map_tag_to_revision($browse_revtag);
|
||||
}
|
||||
$row_count = 0;
|
||||
$max_rev_length = length($start_rev);
|
||||
$max_author_length = 8;
|
||||
@revisions = ($start_rev, ancestor_revisions($start_rev));
|
||||
@revisions = sort by_author @revisions if $opt_sort eq 'author';
|
||||
#@revisions = sort by_author @revisions if $opt_sort eq 'date' && $rev eq 'all';
|
||||
foreach $revision (@revisions)
|
||||
{
|
||||
$author = $revision_author{$revision};
|
||||
next unless $author_arg eq '' || $use_author{$author};
|
||||
|
||||
$log = $revision_log{$revision};
|
||||
$log =~ s/&/&/g;
|
||||
$log =~ s/</</g;
|
||||
$log =~ s/>/>/g;
|
||||
eval ('$log =~ s@\d{4,6}@' . $BUGSYSTEMEXPR . '@g;');
|
||||
$log =~ s/\n|\r|\r\n/<BR>/g;
|
||||
|
||||
if ($bgcolor eq '') {
|
||||
#$bgcolor = ' BGCOLOR="#EEEEEE"';# My browser translates this to white.
|
||||
$bgcolor = ' BGCOLOR="#E7E7E7"'; # Pick a grey that shows up on 8-bit.
|
||||
} else {
|
||||
$bgcolor = '';
|
||||
}
|
||||
|
||||
$output = '';
|
||||
$row_count++;
|
||||
if ($row_count > 20) {
|
||||
$output .= "</TABLE>\n$table_tag";
|
||||
$row_count = 0;
|
||||
}
|
||||
|
||||
$output .= "<TR$bgcolor VALIGN=TOP><TD>"
|
||||
."<A NAME=$revision><A HREF='cvsview2.cgi";
|
||||
if (defined($prev_revision{$revision})) {
|
||||
$output .= "?diff_mode=context&whitespace_mode=show&file=$file_tail"
|
||||
."&root=$root&subdir=$rcs_path&command=DIFF_FRAMESET"
|
||||
."&rev1=$prev_revision{$revision}&rev2=$revision";
|
||||
} else {
|
||||
$output .= "?files=$file_tail"
|
||||
."&root=$root&subdir=$rcs_path\&command=DIRECTORY\&rev2=$revision";
|
||||
$output .= "&branch=$browse_revtag" unless $browse_revtag eq 'HEAD';
|
||||
}
|
||||
$output .= "'>$revision</A>"
|
||||
.' ' x ($max_rev_length - length($revision)).'</TD>';
|
||||
|
||||
$output .= "<TD>".$author
|
||||
.' ' x ($max_author_length - length($author)).'</TD>';
|
||||
$rev_time = $revision_ctime{$revision};
|
||||
# $rev_time =~ s/(19\d\d) (.\d:\d\d)/$1<BR><FONT SIZE=-2>$2<\/FONT>/;
|
||||
|
||||
# jwz: print the date the way "ls" does.
|
||||
#
|
||||
# What ls does is actually: print "Mmm DD HH:MM" unless the file is
|
||||
# more than six months old, or more than 1 hour in the future, in
|
||||
# which case, print "Mmm DD YYYY".
|
||||
#
|
||||
# What the following does is: "Mmm DD HH:MM" unless the year is not
|
||||
# the current year; else print "Mmm DD YYYY".
|
||||
#
|
||||
# If we had $rev_time as an actual time_t instead of as a string,
|
||||
# it would be easy to do the "ls" thing (see the code I wrote for
|
||||
# this in "lxr/source"). -jwz, 15-Jun-98.
|
||||
#
|
||||
{
|
||||
my $current_time = time;
|
||||
my @t = gmtime($current_time);
|
||||
my ($csec, $cmin, $chour, $cmday, $cmon, $cyear) = @t;
|
||||
$cyear += 1900;
|
||||
|
||||
$_ = $rev_time;
|
||||
my ($rday, $rmon, $ryear, $rhour, $rmin) =
|
||||
m/([0-9]+) ([A-Z][a-z]+) ([0-9][0-9]+) +([0-9]+):([0-9]+)/;
|
||||
$rmon =~ s/^(...).*$/$1/;
|
||||
|
||||
if (!$rday) {
|
||||
# parse error -- be annoying so somebody complains.
|
||||
$rev_time = "<BLINK>\"$rev_time\"</BLINK>";
|
||||
} elsif ($cyear ne $ryear) {
|
||||
$rev_time = sprintf("%s %2d %04d", $rmon, $rday, $ryear);
|
||||
} else {
|
||||
$rev_time = sprintf("%s %2d %02d:%02d",
|
||||
$rmon, $rday, $rhour, $rmin);
|
||||
}
|
||||
|
||||
$rev_time = "<FONT SIZE=\"-1\">$rev_time</FONT>";
|
||||
}
|
||||
|
||||
$output .= "<TD NOWRAP ALIGN=RIGHT>$rev_time</TD>";
|
||||
$output .= "<TD> </TD><TD WIDTH=99%>$log</TD>";
|
||||
|
||||
$output .= "</TR>\n";
|
||||
|
||||
print $output;
|
||||
}
|
||||
print "</TABLE>";
|
||||
&print_bottom;
|
||||
|
||||
## END of main script
|
||||
|
||||
sub by_revision {
|
||||
local (@a_parts) = split(/\./,$a);
|
||||
local (@b_parts) = split(/\./,$b);
|
||||
while(1) {
|
||||
local ($aa) = shift @a_parts;
|
||||
local ($bb) = shift @b_parts;
|
||||
return 1 if $aa eq '';
|
||||
return -1 if $bb eq '';
|
||||
return $bb <=> $aa if $aa ne $bb;
|
||||
}
|
||||
}
|
||||
|
||||
sub by_author {
|
||||
local ($a_author) = $revision_author{$a};
|
||||
local ($b_author) = $revision_author{$b};
|
||||
|
||||
return $a_author cmp $b_author if $a_author ne $b_author;
|
||||
return by_revision;
|
||||
}
|
||||
|
||||
sub revision_pad {
|
||||
local ($revision) = @_;
|
||||
return ' ' x ($max_rev_length - length($revision));
|
||||
}
|
||||
|
||||
sub sprint_author {
|
||||
local ($revision) = @_;
|
||||
local ($author) = $revision_author{$revision};
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
sub print_top {
|
||||
local ($title_text) = "for $file_tail (";
|
||||
$title_text .= "$browse_revtag:" unless $browse_revtag eq 'HEAD';
|
||||
$title_text .= $revision if $revision;
|
||||
$title_text .= ")";
|
||||
$title_text =~ s/\(\)//;
|
||||
|
||||
print <<__TOP__;
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>CVS Log $title_text</TITLE>
|
||||
<SCRIPT>
|
||||
|
||||
var event = new Object;
|
||||
|
||||
function who_menu(n,extra,d) {
|
||||
if( parseInt(navigator.appVersion) < 4 ){
|
||||
return true;
|
||||
}
|
||||
l = document.layers['popup'];
|
||||
l.src="../registry/who.cgi?email="+n+extra;
|
||||
l.top = d.target.y - 6;
|
||||
l.left = d.target.x - 6;
|
||||
l.visibility="show";
|
||||
return false;
|
||||
}
|
||||
|
||||
function file_menu(dir,file,prev_rev,rev,root,d) {
|
||||
if( parseInt(navigator.appVersion) < 4 ){
|
||||
return true;
|
||||
}
|
||||
l = document.layers['popup'];
|
||||
l.src="../registry/file.cgi?file="+file+"&dir="+dir+"&prev_rev="+prev_rev+"&rev="+rev+"&cvsroot="+root+"&linked_text="+rev;
|
||||
/* d.target.text */
|
||||
l.top = d.target.y - 6;
|
||||
l.left = d.target.x - 6;
|
||||
l.visibility="show";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
</SCRIPT>
|
||||
|
||||
</HEAD>
|
||||
<BODY BGCOLOR=WHITE TEXT=BLACK>
|
||||
<layer name="popup" onMouseOut="this.visibility='hide';" left=0 top=0 bgcolor="#ffffff" visibility="hide">
|
||||
</layer>
|
||||
|
||||
__TOP__
|
||||
} # print_top
|
||||
|
||||
sub print_usage {
|
||||
local ($linenum_message) = '';
|
||||
local ($new_linenum, $src_roots_list);
|
||||
local ($title_text) = "Usage";
|
||||
|
||||
$src_roots_list = join('<BR>', @src_roots);
|
||||
|
||||
print <<__USAGE__;
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>CVS Log $title_text</TITLE>
|
||||
</HEAD><BODY>
|
||||
<H2>CVS Log Usage</H2>
|
||||
Add parameters to the query string to view a file.
|
||||
<P>
|
||||
<TABLE BORDER CELLPADDING=3>
|
||||
<TR ALIGN=LEFT>
|
||||
<TH>Param</TH>
|
||||
<TH>Default</TH>
|
||||
<TH>Example</TH>
|
||||
<TH>Description</TH>
|
||||
</TR><TR>
|
||||
<TD>file</TD>
|
||||
<TD>--</TD>
|
||||
<TD>ns/cmd/Makefile</TD>
|
||||
<TD>Path to file name</TD>
|
||||
</TR><TR>
|
||||
<TD>root</TD>
|
||||
<TD>$src_roots_list</TD>
|
||||
<TD>/warp/webroot</TD>
|
||||
<TD>CVS root</TD>
|
||||
</TR><TR>
|
||||
<TD>rev</TD>
|
||||
<TD>HEAD</TD>
|
||||
<TD>1.3
|
||||
<BR>ACTRA_branch</TD>
|
||||
<TD>Revision</TD>
|
||||
</TR><TR>
|
||||
<TD>author</TD>
|
||||
<TD>--</TD>
|
||||
<TD>slamm,mtoy</TD>
|
||||
<TD>Filter out these authors</TD>
|
||||
</TR>
|
||||
</TR><TR>
|
||||
<TD>#<rev_number></TD>
|
||||
<TD>--</TD>
|
||||
<TD>#1.2</TD>
|
||||
<TD>Jump to a revision</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
<P>Examples:
|
||||
<TABLE><TR><TD> </TD><TD>
|
||||
<A HREF="cvslog.cgi?file=ns/cmd/Makefile">
|
||||
cvslog.cgi?file=ns/cmd/Makefile</A>
|
||||
</TD></TR><TR><TD> </TD><TD>
|
||||
<A HREF="cvslog.cgi?file=ns/cmd/xfe/mozilla.c&rev=Dogbert4xEscalation_BRANCH">
|
||||
cvslog.cgi?file=ns/cmd/xfe/mozilla.c&rev=Dogbert4xEscalation_BRANCH</A>
|
||||
</TD></TR><TR><TD> </TD><TD>
|
||||
<A HREF="cvslog.cgi?file=projects/bonsai/cvslog.cgi&root=/warp/webroot">
|
||||
cvslog.cgi?file=projects/bonsai/cvslog.cgi&root=/warp/webroot</A>
|
||||
</TD></TR><TR><TD> </TD><TD>
|
||||
<A HREF="cvslog.cgi?file=ns/cmd/xfe/dialogs.c#1.19">
|
||||
cvslog.cgi?file=ns/cmd/xfe/dialogs.c#1.19</A>
|
||||
</TD></TR></TABLE>
|
||||
<P>
|
||||
You may also begin a query with the <A HREF="cvsqueryform.cgi">CVS Query Form</A>.
|
||||
</P>
|
||||
__USAGE__
|
||||
&print_bottom;
|
||||
} # sub print_usage
|
||||
|
||||
sub print_bottom {
|
||||
print <<__BOTTOM__;
|
||||
<HR WIDTH="100%">
|
||||
<FONT SIZE=-1>
|
||||
<A HREF="cvslog.cgi">Page configuration and help</A>.
|
||||
Mail feedback to <A HREF="mailto:slamm\@netscape.com?subject=About the cvslog script"><slamm\@netscape.com></A>.
|
||||
</FONT></BODY>
|
||||
</HTML>
|
||||
__BOTTOM__
|
||||
} # print_bottom
|
||||
|
||||
sub print_useful_links {
|
||||
my ($path) = @_;
|
||||
my ($dir, $file) = $path =~ m@(.*/)?(.+)@;
|
||||
$dir =~ s@/$@@;
|
||||
|
||||
my $lxr_base = "http://cvs-mirror.mozilla.org/webtools/lxr/source";
|
||||
my $diff_base = "cvsview2.cgi";
|
||||
my $blame_base = "cvsblame.cgi";
|
||||
|
||||
# total kludge!! lxr omits the top-level "mozilla" directory...
|
||||
my $lxr_path = $path;
|
||||
$lxr_path =~ s@^ns/@@;
|
||||
$lxr_path =~ s@^mozilla/@@;
|
||||
|
||||
my $lxr_link = "$lxr_base/$lxr_path";
|
||||
my $diff_link = "$diff_base?command=DIRECTORY\&subdir=$dir\&files=$file";
|
||||
my $blame_link = "$blame_base?root=$CVS_ROOT\&file=$path";
|
||||
|
||||
print "<DIV ALIGN=RIGHT>
|
||||
<TABLE BORDER CELLPADDING=10 CELLSPACING=0>
|
||||
<TR>
|
||||
<TD>
|
||||
<TABLE BORDER=0 CELLPADDING=1 CELLSPACING=0>
|
||||
<TR>
|
||||
<TD VALIGN=TOP ALIGN=RIGHT><A HREF=\"$lxr_link\"><B>lxr:</B></A> </TD>
|
||||
<TD>browse the source code as hypertext.</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD VALIGN=TOP ALIGN=RIGHT><A HREF=\"$diff_link\"><B>diff:</B></A> </TD>
|
||||
<TD>compare any two versions.</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD VALIGN=TOP ALIGN=RIGHT><A HREF=\"$blame_link\"><B>blame:</B></A> </TD>
|
||||
<TD>annotate the author of each line.</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
</DIV>
|
||||
";
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
1;
|
||||
|
||||
require 'utils.pl';
|
||||
|
||||
sub cvsmenu {
|
||||
my($extra) = @_;
|
||||
loadConfigData();
|
||||
print "
|
||||
<table border=1 bgcolor=#ffffcc $extra><tr><th>Menu</tr><tr><td>
|
||||
<p><dl>";
|
||||
|
||||
my $pass;
|
||||
my $i;
|
||||
foreach $pass ("cvsqueryform|Query",
|
||||
"rview|Browse",
|
||||
"moduleanalyse|Examine Modules") {
|
||||
($page, $title) = split(/\|/, $pass);
|
||||
print "<b>$title</b><br><ul>\n";
|
||||
foreach $i (@treelist) {
|
||||
my $branch = $treeinfo{$i}->{'branch'};
|
||||
if ($branch ne "") {
|
||||
$branch = "&branch=" . $branch;
|
||||
}
|
||||
$desc = $treeinfo{$i}->{'shortdesc'};
|
||||
if ($desc eq "") {
|
||||
$desc = $treeinfo{$i}->{'description'};
|
||||
}
|
||||
print "<li><a href=$page.cgi?cvsroot=$treeinfo{$i}->{'repository'}&module=$treeinfo{$i}->{'module'}$branch>$desc</a>\n";
|
||||
};
|
||||
print "</ul>\n";
|
||||
};
|
||||
|
||||
if (open(EXTRA, "<data/cvsmenuextra")) {
|
||||
while (<EXTRA>) {
|
||||
print $_;
|
||||
}
|
||||
close EXTRA;
|
||||
}
|
||||
|
||||
print "</dl>
|
||||
<p></tr><tr><td><font size=-1> Questions, Comments, Feature requests? mail <a href=mailto:terry\@netscape.com>terry</a>
|
||||
</tr></table>
|
||||
";
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,647 @@
|
|||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
require 'lloydcgi.pl';
|
||||
require 'utils.pl';
|
||||
use Date::Parse;
|
||||
|
||||
loadConfigData();
|
||||
$CVS_ROOT = $form{"cvsroot"};
|
||||
|
||||
require 'timelocal.pl';
|
||||
require 'cvsquery.pl';
|
||||
|
||||
$| = 1;
|
||||
|
||||
$sm_font_tag = "<font face='Arial,Helvetica' size=-2>";
|
||||
|
||||
print "Content-type: text/html
|
||||
|
||||
";
|
||||
|
||||
$script_str='';
|
||||
&setup_script;
|
||||
|
||||
print "$script_str";
|
||||
|
||||
#print "<pre>";
|
||||
|
||||
|
||||
$CVS_REPOS_SUFIX = $CVS_ROOT;
|
||||
$CVS_REPOS_SUFIX =~ s/\//_/g;
|
||||
|
||||
$CHECKIN_DATA_FILE = "data/checkinlog${CVS_REPOS_SUFIX}";
|
||||
$CHECKIN_INDEX_FILE = "data/index${CVS_REPOS_SUFIX}";
|
||||
|
||||
|
||||
$SORT_HEAD="bgcolor=\"#DDDDDD\"";
|
||||
|
||||
#
|
||||
# Log the query
|
||||
open( LOG, ">>data/querylog.txt");
|
||||
$t = time;
|
||||
print LOG "$ENV{'REMOTE_ADDR'} $t $ENV{'QUERY_STRING'}\n";
|
||||
close(LOG);
|
||||
|
||||
#
|
||||
# build a module map
|
||||
#
|
||||
$query_module = $form{'module'};
|
||||
|
||||
#
|
||||
# allow ?file=/a/b/c/foo.c to be synonymous with ?dir=/a/b/c&file=foo.c
|
||||
#
|
||||
if ( $form{'dir'} eq '' ) {
|
||||
my ( $d, $f ) = $form{'file'} =~ m@(.*?/)([^/]*)$@;
|
||||
$form{'dir'} = $d;
|
||||
$form{'file'} = $f;
|
||||
}
|
||||
|
||||
#
|
||||
# build a directory map
|
||||
#
|
||||
@query_dirs = split(/[;, \t]+/, $form{'dir'});
|
||||
|
||||
$query_file = $form{'file'};
|
||||
$query_filetype = $form{'filetype'};
|
||||
$query_logexpr = $form{'logexpr'};
|
||||
|
||||
|
||||
|
||||
|
||||
#
|
||||
# date
|
||||
#
|
||||
$query_date_type = $form{'date'};
|
||||
if( $query_date_type eq 'hours' ){
|
||||
$query_date_min = time - $form{'hours'}*60*60;
|
||||
}
|
||||
elsif( $query_date_type eq 'day' ){
|
||||
$query_date_min = time - 24*60*60;
|
||||
}
|
||||
elsif( $query_date_type eq 'week' ){
|
||||
$query_date_min = time - 7*24*60*60;
|
||||
}
|
||||
elsif( $query_date_type eq 'month' ){
|
||||
$query_date_min = time - 30*24*60*60;
|
||||
}
|
||||
elsif( $query_date_type eq 'all' ){
|
||||
$query_date_min = 0;
|
||||
}
|
||||
elsif( $query_date_type eq 'explicit' ){
|
||||
if ($form{'mindate'} ne "") {
|
||||
$query_date_min = parse_date($form{'mindate'});
|
||||
}
|
||||
|
||||
if ($form{'maxdate'} ne "") {
|
||||
$query_date_max = parse_date($form{'maxdate'});
|
||||
}
|
||||
}
|
||||
else {
|
||||
$query_date_min = time-60*60*2;
|
||||
}
|
||||
|
||||
#
|
||||
# who
|
||||
#
|
||||
$query_who = $form{'who'};
|
||||
$query_whotype = $form{'whotype'};
|
||||
|
||||
|
||||
$show_raw = $form{'raw'} ne '';
|
||||
|
||||
#
|
||||
# branch
|
||||
#
|
||||
$query_branch = $form{'branch'};
|
||||
$query_branchtype = $form{'branchtype'};
|
||||
|
||||
|
||||
#
|
||||
# tags
|
||||
#
|
||||
$query_begin_tag = $form{'begin_tag'};
|
||||
$query_end_tag = $form{'end_tag'};
|
||||
|
||||
|
||||
#
|
||||
# Get the query in english and print it.
|
||||
#
|
||||
$t = $e = &query_to_english;
|
||||
$t =~ s/<[^>]*>//g;
|
||||
|
||||
$query_debug = $form{'debug'};
|
||||
|
||||
$result= &query_checkins( $mod_map );
|
||||
|
||||
for $i (@{$result}) {
|
||||
$w{"$i->[$CI_WHO]\@netscape.com"} = 1;
|
||||
}
|
||||
|
||||
@p = sort keys %w;
|
||||
$pCount = @p;
|
||||
$s = join(",%20", @p);
|
||||
|
||||
$e =~ s/Checkins in/In/;
|
||||
|
||||
my $menu = "
|
||||
<p align=center>$e
|
||||
<p align=left>
|
||||
<a href=cvsqueryform.cgi?$ENV{QUERY_STRING}>Modify Query</a>
|
||||
<br><a href=mailto:$s>Mail everyone on this page</a>
|
||||
<NOBR>($pCount people)</NOBR>
|
||||
";
|
||||
|
||||
EmitHtmlTitleAndHeader($t, "CVS Checkins", "$menu");
|
||||
|
||||
#
|
||||
# Test code to print the results
|
||||
#
|
||||
|
||||
$|=1;
|
||||
|
||||
if( !$show_raw ) {
|
||||
|
||||
if( $form{"sortby"} eq "Who" ){
|
||||
$result = [sort {
|
||||
$a->[$CI_WHO] cmp $b->[$CI_WHO]
|
||||
|| $b->[$CI_DATE] <=> $a->[$CI_DATE]
|
||||
} @{$result}] ;
|
||||
$head_who = $SORT_HEAD;
|
||||
}
|
||||
elsif( $form{"sortby"} eq "File" ){
|
||||
$result = [sort {
|
||||
$a->[$CI_FILE] cmp $b->[$CI_FILE]
|
||||
|| $b->[$CI_DATE] <=> $a->[$CI_DATE]
|
||||
|| $a->[$CI_DIRECTORY] cmp $b->[$CI_DIRECTORY]
|
||||
} @{$result}] ;
|
||||
$head_file = $SORT_HEAD;
|
||||
}
|
||||
elsif( $form{"sortby"} eq "Directory" ){
|
||||
$result = [sort {
|
||||
$a->[$CI_DIRECTORY] cmp $b->[$CI_DIRECTORY]
|
||||
|| $a->[$CI_FILE] cmp $b->[$CI_FILE]
|
||||
|| $b->[$CI_DATE] <=> $a->[$CI_DATE]
|
||||
} @{$result}] ;
|
||||
$head_directory = $SORT_HEAD;
|
||||
}
|
||||
elsif( $form{"sortby"} eq "Change Size" ){
|
||||
$result = [sort {
|
||||
|
||||
($b->[$CI_LINES_ADDED]- $b->[$CI_LINES_REMOVED])
|
||||
<=> ($a->[$CI_LINES_ADDED]- $a->[$CI_LINES_REMOVED])
|
||||
#|| $b->[$CI_DATE] <=> $a->[$CI_DATE]
|
||||
} @{$result}] ;
|
||||
$head_delta = $SORT_HEAD;
|
||||
}
|
||||
else{
|
||||
$result = [sort {$b->[$CI_DATE] <=> $a->[$CI_DATE]} @{$result}] ;
|
||||
$head_date = $SORT_HEAD;
|
||||
}
|
||||
|
||||
&print_result($result);
|
||||
}
|
||||
else {
|
||||
print "<pre>";
|
||||
for $ci (@$result) {
|
||||
$ci->[$CI_LOG] = '';
|
||||
$s = join("|",@$ci);
|
||||
print "$s\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# code to debug the modules_map
|
||||
#
|
||||
#print "<PRE>\n";
|
||||
#while( ($k,$v) = each(%{$mod_map})) {
|
||||
# print "$k=$v\n";
|
||||
#}
|
||||
|
||||
#
|
||||
#
|
||||
#
|
||||
sub print_tcl {
|
||||
local($result) = @_;
|
||||
local($t, $count,$first,$i, $k, $files);
|
||||
|
||||
$t = time;
|
||||
print TCLOUT "set treeopen 0\n" .
|
||||
"set lastgoodtimestamp $t\n" .
|
||||
"set closetimestamp $t\n";
|
||||
$count = 0;
|
||||
$first = 0;
|
||||
$i = 1;
|
||||
|
||||
|
||||
$max = @{$result}+1;
|
||||
|
||||
while( $i < $max ){
|
||||
$c1 = $result->[$first];
|
||||
$c2 = $result->[$i];
|
||||
if( $i == $max-1
|
||||
|| $c1->[$CI_DATE] != $c2->[$CI_DATE]
|
||||
|| $c1->[$CI_DIR] ne $c2->[$CI_DIR]
|
||||
|| $c1->[$CI_WHO] ne $c2->[$CI_WHO]
|
||||
) {
|
||||
$files = '{';
|
||||
$fu = '{';
|
||||
$k = $first;
|
||||
while( $k < $i ){
|
||||
$files .= $result->[$k][$CI_FILE] . " ";
|
||||
$fu .= &make_fullinfo( $result->[$k] );
|
||||
$k++;
|
||||
}
|
||||
$files .= '}';
|
||||
$fu .= '}';
|
||||
print TCLOUT "set ci-${count}(date) $c1->[$CI_DATE]\n" .
|
||||
"set ci-${count}(dir) $c1->[$CI_DIR]\n" .
|
||||
"set ci-${count}(person) $c1->[$CI_WHO]\n" .
|
||||
"set ci-${count}(files) $files\n" .
|
||||
"set ci-${count}(fullinfo) $fu\n" .
|
||||
"set ci-${count}(log) \{$c1->[$CI_LOG]\}\n" .
|
||||
"set ci-${count}(treeopen) 1\n";
|
||||
$count++;
|
||||
$first = $i;
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
|
||||
sub make_fullinfo{
|
||||
local( $ci ) = @_;
|
||||
local( $s );
|
||||
|
||||
$a = &tcl_value( $ci->[$CI_FILE] );
|
||||
$b = &tcl_value( $ci->[$CI_REV] );
|
||||
$c = &tcl_value( $ci->[$CI_LINES_ADDED] );
|
||||
$d = &tcl_value( $ci->[$CI_LINES_REMOVED] );
|
||||
$e = &tcl_value( $ci->[$CI_STICKY] );
|
||||
|
||||
return "{$a $b $c $d $e}";
|
||||
}
|
||||
|
||||
sub tcl_value {
|
||||
local( $a ) = @_;
|
||||
|
||||
if( $a eq '' ){
|
||||
return '{}';
|
||||
}
|
||||
else {
|
||||
return $a;
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
#
|
||||
#
|
||||
sub print_result {
|
||||
local($result) = @_;
|
||||
local($ci,$i,$k,$j,$max, $l, $span);
|
||||
|
||||
&print_head;
|
||||
|
||||
$i = 20;
|
||||
$k = 0;
|
||||
$max = @{$result};
|
||||
|
||||
while( $k < $max ){
|
||||
$ci = $result->[$k];
|
||||
$span = 1;
|
||||
if( ($l = $ci->[$CI_LOG]) ne '' ){
|
||||
#
|
||||
# Calculate the number of consequitive logs that are
|
||||
# the same and nuke them
|
||||
#
|
||||
$j = $k+1;
|
||||
while( $j < $max && $result->[$j]->[$CI_LOG] eq $l ){
|
||||
$result->[$j]->[$CI_LOG] = '';
|
||||
$j++;
|
||||
}
|
||||
|
||||
#
|
||||
# Make sure we don't break over a description block
|
||||
#
|
||||
$span = $j-$k;
|
||||
if( $span-1 > $i ){
|
||||
$i = $j-$k;
|
||||
}
|
||||
}
|
||||
|
||||
&print_ci( $ci, $span );
|
||||
|
||||
|
||||
if( $i <= 0 ){
|
||||
$i = 20;
|
||||
print "</TABLE><TABLE border cellspacing=2>\n";
|
||||
}
|
||||
else {
|
||||
$i--;
|
||||
}
|
||||
$k++;
|
||||
}
|
||||
|
||||
&print_foot;
|
||||
}
|
||||
|
||||
sub print_ci {
|
||||
local($ci, $span) = @_;
|
||||
local($sec,$minute,$hour,$mday,$mon,$year,$t);
|
||||
local($log);
|
||||
|
||||
($sec,$minute,$hour,$mday,$mon,$year) = localtime( $ci->[$CI_DATE] );
|
||||
$t = sprintf("%02d/%02d/%02d %02d:%02d",$mon+1,$mday,$year,$hour,$minute);
|
||||
|
||||
$log = &html_log($ci->[$CI_LOG]);
|
||||
$rev = $ci->[$CI_REV];
|
||||
|
||||
print "<tr>\n";
|
||||
|
||||
print "<TD>${sm_font_tag}$t</font>";
|
||||
print "<TD><a href='../registry/who.cgi?email=$ci->[$CI_WHO]' "
|
||||
. "onClick=\"return js_who_menu('$ci->[$CI_WHO]','',event);\" >"
|
||||
. "$ci->[$CI_WHO]</a>\n";
|
||||
print "<TD><a href='cvsview2.cgi?subdir=$ci->[$CI_DIR]&files=$ci->[$CI_FILE]\&command=DIRECTORY&branch=$query_branch&root=$CVS_ROOT'\n"
|
||||
. " onclick=\"return js_file_menu('$CVS_ROOT', '$ci->[$CI_DIR]','$ci->[$CI_FILE]','$ci->[$CI_REV]','$query_branch',event)\">\n";
|
||||
# if( (length $ci->[$CI_FILE]) + (length $ci->[$CI_DIR]) > 30 ){
|
||||
# $d = $ci->[$CI_DIR];
|
||||
# if( (length $ci->[$CI_DIR]) > 30 ){
|
||||
# $d =~ s/([^\n]*\/)(classes\/)/$1classes\/<br>  /;
|
||||
# # Insert a <BR> before any directory named
|
||||
# # 'classes.'
|
||||
# }
|
||||
# print " $d/<br> $ci->[$CI_FILE]<a>\n";
|
||||
# }
|
||||
# else{
|
||||
# print " $ci->[$CI_DIR]/$ci->[$CI_FILE]<a>\n";
|
||||
# }
|
||||
$d = "$ci->[$CI_DIR]/$ci->[$CI_FILE]";
|
||||
if( $query_module eq 'allrepositories' ){ $d = "$ci->[$CI_REPOSITORY]/$d"; }
|
||||
$d =~ s:/:/ :g; # Insert a whitespace after any slash, so that
|
||||
# we'll break long names at a reasonable place.
|
||||
print "$d\n";
|
||||
|
||||
if( $rev ne '' ){
|
||||
$prevrev = &PrevRev( $rev );
|
||||
print "<TD>${sm_font_tag}<a href='cvsview2.cgi?diff_mode=".
|
||||
"context\&whitespace_mode=show\&subdir=".
|
||||
$ci->[$CI_DIR] . "\&command=DIFF_FRAMESET\&file=" .
|
||||
$ci->[$CI_FILE] . "\&rev1=$prevrev&rev2=$rev&root=$CVS_ROOT'>$rev</a></font>\n";
|
||||
}
|
||||
else {
|
||||
print "<TD>\ \n";
|
||||
}
|
||||
|
||||
if( !$query_branch_head ){
|
||||
print "<TD><TT><FONT SIZE=-1>$ci->[$CI_BRANCH] </FONT></TT>\n";
|
||||
}
|
||||
print "<TD>${sm_font_tag}$ci->[$CI_LINES_ADDED]/$ci->[$CI_LINES_REMOVED]</font> \n";
|
||||
if( $log ne '' ){
|
||||
eval ('$log =~ s@\d{4,6}@' . $BUGSYSTEMEXPR . '@g;');
|
||||
$log =~ s/([ #\t])([0-9][0-9][0-9][0-9][0-9])([^0-9])/$1<a href='http:\/\/scopus.mcom.com\/bugsplat\/show_bug.cgi?id=$2'>$2<\/a>$3/g;
|
||||
# Makes numbers into links to bugsplat.
|
||||
|
||||
$log =~ s/\n/<BR>/g;
|
||||
# Makes newlines into <BR>'s
|
||||
|
||||
if( $span > 1 ){
|
||||
print "<TD VALIGN=TOP ROWSPAN=$span>$log\n";
|
||||
}
|
||||
else {
|
||||
print "<TD VALIGN=TOP>$log\n";
|
||||
}
|
||||
}
|
||||
print "</tr>\n";
|
||||
}
|
||||
|
||||
sub print_head {
|
||||
|
||||
if ($versioninfo ne "") {
|
||||
print "<FORM action='multidiff.cgi' method=get>";
|
||||
print "<INPUT TYPE='HIDDEN' name='allchanges' value = '$versioninfo'>";
|
||||
print "<INPUT TYPE='HIDDEN' name='cvsroot' value = '$CVS_ROOT'>";
|
||||
print "<INPUT TYPE=SUBMIT VALUE='Show me ALL the Diffs'>";
|
||||
print "</FORM>";
|
||||
print "<tt>(+$lines_added/$lines_removed)</tt> Lines changed.";
|
||||
}
|
||||
|
||||
$anchor = $ENV{QUERY_STRING};
|
||||
$anchor =~ s/\&sortby\=[A-Za-z\ \+]*//g;
|
||||
$anchor = "<a href=cvsquery.cgi?$anchor";
|
||||
|
||||
print "
|
||||
<TABLE border cellspacing=2>
|
||||
<b><TR ALIGN=LEFT>
|
||||
<TH width=2% $head_date>$anchor>When</a>
|
||||
<TH width=2% $head_who>${anchor}&sortby=Who>Who</a>
|
||||
<TH width=45% $head_file>${anchor}&sortby=File>File</a>
|
||||
<TH width=2%>Rev
|
||||
";
|
||||
|
||||
$descwidth = 47;
|
||||
if( !$query_branch_head ){
|
||||
print "<TH width=2%>Branch\n";
|
||||
$descwidth -= 2;
|
||||
}
|
||||
|
||||
print "
|
||||
<TH width=2% $head_delta>${anchor}&sortby=Change+Size>+/-</a>
|
||||
<TH WIDTH=$descwidth%>Description
|
||||
</TR></b>
|
||||
";
|
||||
}
|
||||
|
||||
|
||||
sub print_foot {
|
||||
print "</TABLE>";
|
||||
print "<br><br>";
|
||||
}
|
||||
|
||||
sub html_log {
|
||||
local( $log ) = @_;
|
||||
$log =~ s/&/&/g;
|
||||
$log =~ s/</</g;
|
||||
return $log;
|
||||
}
|
||||
|
||||
sub PrevRev {
|
||||
local( $rev ) = @_;
|
||||
local( $i, $j, $ret, @r );
|
||||
|
||||
@r = split( /\./, $rev );
|
||||
|
||||
$i = @r-1;
|
||||
|
||||
$r[$i]--;
|
||||
if( $r[$i] == 0 ){
|
||||
$i -= 2;
|
||||
}
|
||||
|
||||
$j = 0;
|
||||
while( $j < $i ){
|
||||
$ret .= "$r[$j]\.";
|
||||
$j++
|
||||
}
|
||||
$ret .= $r[$i];
|
||||
}
|
||||
|
||||
|
||||
sub parse_date {
|
||||
my($d) = @_;
|
||||
|
||||
my($result) = str2time($d);
|
||||
if (defined $result) {
|
||||
return $result;
|
||||
} elsif ($d > 7000000) {
|
||||
return $d;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
sub setup_script {
|
||||
|
||||
$script_str =<<'ENDJS';
|
||||
<script>
|
||||
function js_who_menu(n,extra,d) {
|
||||
if( parseInt(navigator.appVersion) < 4 ){
|
||||
return true;
|
||||
}
|
||||
l = document.layers['popup'];
|
||||
l.src="../registry/who.cgi?email="+n+extra;
|
||||
l.top = d.target.y - 6;
|
||||
l.left = d.target.x - 6;
|
||||
if( l.left + l.clipWidth > window.width ){
|
||||
l.left = window.width - l.clipWidth;
|
||||
}
|
||||
l.visibility="show";
|
||||
return false;
|
||||
}
|
||||
|
||||
function js_file_menu(repos,dir,file,rev,branch,d) {
|
||||
if( parseInt(navigator.appVersion) < 4 ){
|
||||
return true;
|
||||
}
|
||||
l = document.layers['popup'];
|
||||
l.src="../registry/file.cgi?cvsroot="+repos+"&file="+file+"&dir="+dir+"&rev="+rev+"&branch="+branch+"&linked_text="+d.target.text;
|
||||
|
||||
l.top = d.target.y - 6;
|
||||
l.left = d.target.x - 6;
|
||||
if( l.left + l.clipWidth > window.width ){
|
||||
l.left = window.width - l.clipWidth;
|
||||
}
|
||||
l.visibility="show";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<layer name="popup" onMouseOut="this.visibility='hide';" left=0 top=0 bgcolor="#ffffff" visibility="hide">
|
||||
</layer>
|
||||
|
||||
ENDJS
|
||||
|
||||
}
|
||||
|
||||
#
|
||||
# Actually do the query
|
||||
#
|
||||
sub query_to_english {
|
||||
my $english = 'Checkins ';
|
||||
|
||||
if( $query_module eq 'allrepositories' ){
|
||||
$english .= "to <i>All Repositories</i> ";
|
||||
}
|
||||
elsif( $query_module ne 'all' && @query_dirs == 0 ){
|
||||
$english .= "to module <i>$query_module</i> ";
|
||||
}
|
||||
elsif( $form{dir} ne "" ) {
|
||||
my $word = "directory";
|
||||
if (@query_dirs > 1) {
|
||||
$word = "directories";
|
||||
}
|
||||
$english .= "to $word <i>$form{dir}</i> ";
|
||||
}
|
||||
|
||||
if ($query_file ne "") {
|
||||
if ($english ne 'Checkins ') {
|
||||
$english .= "and ";
|
||||
}
|
||||
$english .= "to file $query_file ";
|
||||
}
|
||||
|
||||
if( ! ($query_branch =~ /^[ ]*HEAD[ ]*$/i) ){
|
||||
if($query_branch eq '' ){
|
||||
$english .= "on all branches ";
|
||||
}
|
||||
else {
|
||||
$english .= "on branch <i>$query_branch</i> ";
|
||||
}
|
||||
}
|
||||
|
||||
if( $query_who ne '' ){
|
||||
$english .= "by $query_who ";
|
||||
}
|
||||
|
||||
$query_date_type = $form{'date'};
|
||||
if( $query_date_type eq 'hours' ){
|
||||
$english .="in the last $form{hours} hours";
|
||||
}
|
||||
elsif( $query_date_type eq 'day' ){
|
||||
$english .="in the last day";
|
||||
}
|
||||
elsif( $query_date_type eq 'week' ){
|
||||
$english .="in the last week";
|
||||
}
|
||||
elsif( $query_date_type eq 'month' ){
|
||||
$english .="in the last month";
|
||||
}
|
||||
elsif( $query_date_type eq 'all' ){
|
||||
$english .="since the beginning of time";
|
||||
}
|
||||
elsif( $query_date_type eq 'explicit' ){
|
||||
if ( $form{mindate} ne "" && $form{maxdate} ne "" ) {
|
||||
$w1 = "between";
|
||||
$w2 = "and" ;
|
||||
}
|
||||
else {
|
||||
$w1 = "since";
|
||||
$w2 = "before";
|
||||
}
|
||||
|
||||
if( $form{'mindate'} ne "" ){
|
||||
$dd = &parse_date($form{'mindate'});
|
||||
($sec,$minute,$hour,$mday,$mon,$year) = localtime( $dd );
|
||||
$t = sprintf("%02d/%02d/%02d %02d:%02d",$mon+1,$mday,$year,$hour,$minute);
|
||||
$english .= "$w1 <i>$t</i> ";
|
||||
}
|
||||
|
||||
if( $form{'maxdate'} ne "" ){
|
||||
$dd = &parse_date($form{'maxdate'});
|
||||
($sec,$minute,$hour,$mday,$mon,$year) = localtime( $dd );
|
||||
$t = sprintf("%02d/%02d/%02d %02d:%02d",$mon+1,$mday,$year,$hour,$minute);
|
||||
$english .= "$w2 <i>$t</i> ";
|
||||
}
|
||||
}
|
||||
return $english . ":";
|
||||
}
|
||||
|
|
@ -0,0 +1,443 @@
|
|||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
require 'utils.pl';
|
||||
|
||||
#
|
||||
# Constants
|
||||
#
|
||||
$CI_CHANGE=0;
|
||||
$CI_DATE=1;
|
||||
$CI_WHO=2;
|
||||
$CI_REPOSITORY=3;
|
||||
$CI_DIR=4;
|
||||
$CI_FILE=5;
|
||||
$CI_REV=6;
|
||||
$CI_STICKY=7;
|
||||
$CI_BRANCH=8;
|
||||
$CI_LINES_ADDED=9;
|
||||
$CI_LINES_REMOVED=10;
|
||||
$CI_LOG=11;
|
||||
|
||||
$NOT_LOCAL = 1;
|
||||
$IS_LOCAL = 2;
|
||||
|
||||
|
||||
if( $CVS_ROOT eq "" ){
|
||||
$CVS_ROOT = pickDefaultRepository();
|
||||
}
|
||||
|
||||
#global variables
|
||||
|
||||
$lines_added = 0;
|
||||
$lines_removed = 0;
|
||||
|
||||
$modules = {};
|
||||
|
||||
if( $ENV{"OS"} eq "Windows_NT" ){
|
||||
# for debugging purposes
|
||||
$CVS_MODULES='k:/warp/projects/bonsai/modules';
|
||||
}
|
||||
else {
|
||||
$CVS_MODULES="${CVS_ROOT}/CVSROOT/modules";
|
||||
#$CVS_MODULES='data/modules';
|
||||
}
|
||||
|
||||
open( MOD, "<$CVS_MODULES") || die "can't open ${CVS_MODULES}";
|
||||
&parse_modules;
|
||||
close( MOD );
|
||||
|
||||
1;
|
||||
|
||||
#
|
||||
# Actually do the query
|
||||
#
|
||||
sub query_checkins {
|
||||
local($mod_map) = @_;
|
||||
local($ci,$result,$lastlog,$rev,$begin_tag,$end_tag);
|
||||
|
||||
if( $query_module ne 'all' && $query_module ne 'allrepositories' && @query_dirs == 0 ){
|
||||
$have_mod_map = 1;
|
||||
$mod_map = &get_module_map( $query_module );
|
||||
}
|
||||
else {
|
||||
$have_mod_map = 0;
|
||||
$mod_map = {};
|
||||
}
|
||||
|
||||
for $i (@query_dirs ){
|
||||
$i =~ s:^/::; # Strip leading slash.
|
||||
$i =~ s:/$::; # Strip trailing slash.
|
||||
|
||||
if( !$have_mod_map ){
|
||||
$mod_map = {};
|
||||
$have_mod_map = 1;
|
||||
}
|
||||
$mod_map->{$i} = $NOT_LOCAL;
|
||||
}
|
||||
|
||||
if( $query_branch =~ /^[ ]*HEAD[ ]*$/i ){
|
||||
$query_branch_head = 1;
|
||||
}
|
||||
|
||||
$begin_tag = "";
|
||||
$end_tag = "";
|
||||
|
||||
if ( $query_begin_tag ne '') {
|
||||
$begin_tag = load_tag($query_begin_tag);
|
||||
}
|
||||
|
||||
if ( $query_end_tag ne '') {
|
||||
$end_tag = load_tag($query_end_tag);
|
||||
}
|
||||
|
||||
|
||||
$result = [];
|
||||
|
||||
my $db = ConnectToDatabase();
|
||||
|
||||
my $qstring = "select type, UNIX_TIMESTAMP(when), people.who, repositories.repository, dirs.dir, files.file, revision, stickytag, branches.branch, addedlines, removedlines, descs.description from checkins,people,repositories,dirs,files,branches,descs where people.id=whoid and repositories.id=repositoryid and dirs.id=dirid and files.id=fileid and branches.id=branchid and descs.id=descid";
|
||||
|
||||
if( $query_module ne 'allrepositories' ){
|
||||
$qstring .= " and repositories.repository = '$CVS_ROOT'";
|
||||
}
|
||||
|
||||
if ($query_date_min) {
|
||||
my $t = formatSqlTime($query_date_min);
|
||||
$qstring .= " and when >= '$t'";
|
||||
}
|
||||
if ($query_date_max) {
|
||||
my $t = formatSqlTime($query_date_max);
|
||||
$qstring .= " and when <= '$t'";
|
||||
}
|
||||
if ($query_branch_head) {
|
||||
$qstring .= " and branches.branch = ''";
|
||||
} elsif ($query_branch ne '') {
|
||||
my $q = SqlQuote($query_branch);
|
||||
if ($query_branchtype eq 'regexp') {
|
||||
$qstring .=
|
||||
" and branches.branch regexp '$q'";
|
||||
} else {
|
||||
$qstring .=
|
||||
" and (branches.branch = '$q' or branches.branch = 'T$q')";
|
||||
}
|
||||
}
|
||||
|
||||
if( $query_file ne '') {
|
||||
my $q = SqlQuote($query_file);
|
||||
if ($query_filetype eq 'regexp') {
|
||||
$qstring .= " and files.file regexp '$q'";
|
||||
} else {
|
||||
$qstring .= " and files.file = '$q'";
|
||||
}
|
||||
}
|
||||
if ($query_who ne '') {
|
||||
my $q = SqlQuote($query_who);
|
||||
if ($query_whotype eq 'regexp') {
|
||||
$qstring .= " and people.who regexp '$q'";
|
||||
} else {
|
||||
$qstring .= " and people.who = '$q'";
|
||||
}
|
||||
}
|
||||
|
||||
if ($query_logexpr ne '') {
|
||||
my $q = SqlQuote($query_logexpr);
|
||||
$qstring .= " and descs.description regexp '$q'";
|
||||
}
|
||||
|
||||
if ($query_debug) {
|
||||
print "<pre wrap> Query: $qstring</PRE>";
|
||||
}
|
||||
|
||||
$query = $db->Query($qstring) || die $Mysql::db_errstr;
|
||||
|
||||
$lastlog = 0;
|
||||
while(@row = $query->fetchrow) {
|
||||
$ci = [];
|
||||
# print "<pre>";
|
||||
for ($i=0 ; $i<=$CI_LOG ; $i++) {
|
||||
$ci->[$i] = $row[$i];
|
||||
# print "$row[$i] ";
|
||||
}
|
||||
# print "</pre>";
|
||||
|
||||
|
||||
if( $have_mod_map &&
|
||||
!&in_module( $mod_map, $ci->[$CI_DIR], $ci->[$CI_FILE] ) ){
|
||||
next;
|
||||
}
|
||||
|
||||
if( $begin_tag) {
|
||||
$key = "$ci->[$CI_DIR]/$ci->[$CI_FILE]";
|
||||
$rev = $begin_tag->{$key};
|
||||
print "<BR>$key begintag is $rev<BR>\n";
|
||||
if ($rev == "" || rev_is_after($ci->[$CI_REV], $rev)) {
|
||||
next;
|
||||
}
|
||||
}
|
||||
|
||||
if( $end_tag) {
|
||||
$key = "$ci->[$CI_DIR]/$ci->[$CI_FILE]";
|
||||
$rev = $end_tag->{$key};
|
||||
print "<BR>$key endtag is $rev<BR>\n";
|
||||
if ($rev == "" || rev_is_after($rev, $ci->[$CI_REV])) {
|
||||
next;
|
||||
}
|
||||
}
|
||||
|
||||
if( $query_logexpr ne '' && !($ci->[$CI_LOG] =~ /$query_logexpr/i) ){
|
||||
next;
|
||||
}
|
||||
|
||||
push( @$result, $ci );
|
||||
}
|
||||
|
||||
for $ci (@{$result}) {
|
||||
$lines_added += $ci->[$CI_LINES_ADDED];
|
||||
$lines_removed += $ci->[$CI_LINES_REMOVED];
|
||||
$versioninfo .= "$ci->[$CI_WHO]|$ci->[$CI_DIR]|$ci->[$CI_FILE]|$ci->[$CI_REV],";
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
sub load_tag {
|
||||
my $tagname = @_[0];
|
||||
|
||||
my $tagfile;
|
||||
my $cvssuffix;
|
||||
my $s;
|
||||
my @line;
|
||||
my $time;
|
||||
my $cmd;
|
||||
my $dir;
|
||||
|
||||
$cvssuffix = $CVS_ROOT;
|
||||
$cvssuffix =~ s/\//_/g;
|
||||
|
||||
$s = $tagname;
|
||||
|
||||
$s =~ s/ /\%20/g;
|
||||
$s =~ s/\%/\%25/g;
|
||||
$s =~ s/\//\%2f/g;
|
||||
$s =~ s/\?/\%3f/g;
|
||||
$s =~ s/\*/\%2a/g;
|
||||
|
||||
$tagfile = "data/taginfo/$cvssuffix/$s";
|
||||
|
||||
open(TAG, "<$tagfile") || die "Unknown tag $tagname";
|
||||
$result = {};
|
||||
|
||||
|
||||
print "<br>parsing tag $tagname</br>\n";
|
||||
while ( <TAG> ) {
|
||||
chop;
|
||||
@line = split(/\|/);
|
||||
$time = shift @line;
|
||||
$cmd = shift @line;
|
||||
if ($cmd != "add") {
|
||||
# We ought to be able to cope with these... XXX
|
||||
next;
|
||||
}
|
||||
$dir = shift @line;
|
||||
$dir =~ s:^$CVS_ROOT/::;
|
||||
$dir =~ s:^\./::;
|
||||
|
||||
while (@line) {
|
||||
$file = shift @line;
|
||||
$file = "$dir/$file";
|
||||
$version = shift @line;
|
||||
$result->{$file} = $version;
|
||||
print "<br>Added ($file,$version) for tag $tagname<br>\n";
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
sub rev_is_after {
|
||||
my $r1 = shift @_;
|
||||
my $r2 = shift @_;
|
||||
|
||||
my @a = split /:/, $r1;
|
||||
my @b = split /:/, $r2;
|
||||
|
||||
if (@b > @a) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (@b < @a) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (my $i=0 ; $i<@a ; $i++) {
|
||||
if ($a[$i] > $b[$i]) {return 1;}
|
||||
if ($a[$i] < $b[$i]) {return 0;}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
sub find_date_offset {
|
||||
local( $o, $d, $done, $line );
|
||||
$done = 0;
|
||||
local($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
|
||||
$atime,$mtime,$ctime,$blksize,$blocks) = stat($CHECKIN_INDEX_FILE);
|
||||
if ($mtime eq "" || time() - $mtime> 24 * 60 * 60) {
|
||||
print "<h1>Please wait -- rebuilding index file...</h1>\n";
|
||||
system "./cvsindex.pl $CVS_ROOT";
|
||||
print "<h1>...OK, done.</h1>\n";
|
||||
}
|
||||
Lock();
|
||||
if(! open(IDX , "<$CHECKIN_INDEX_FILE") ){
|
||||
print "<h1>can't open index</h1>";
|
||||
Unlock();
|
||||
return 0;
|
||||
}
|
||||
$i = 0;
|
||||
while( ($line = <IDX>) && !$done){
|
||||
chop($line);
|
||||
($o,$d) = split(/\|/,$line);
|
||||
if( $d && $query_date_min > $d ){
|
||||
$done = 1;
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
if( $F_DEBUG ){
|
||||
print "seekdate($d) seekoffset($o) readcount($i)\n";
|
||||
}
|
||||
close IDX;
|
||||
Unlock();
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
sub in_module {
|
||||
local($mod_map, $dirname, $filename ) = @_;
|
||||
local( @path );
|
||||
local( $i, $fp, $local );
|
||||
|
||||
#
|
||||
#quick check if it is already in there.
|
||||
#
|
||||
if( $mod_map{$dirname} ){
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@path = split(/\//, $dirname);
|
||||
|
||||
$fp = '';
|
||||
|
||||
for( $i = 0; $i < @path; $i++){
|
||||
|
||||
$fp .= ($fp ne '' ? '/' : '') . $path[$i];
|
||||
|
||||
if( $local = $mod_map->{$fp} ){
|
||||
if( $local == $IS_LOCAL ){
|
||||
if( $i == (@path-1) ){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
# Add directories to the map as we encounter them so we go
|
||||
# faster
|
||||
if( $mod_map{$dirname} == 0 ){
|
||||
$mod_map{$dirname} = $IS_LOCAL;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( $mod_map->{ $fp . '/' . $filename} ) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub get_module_map {
|
||||
local($name) = @_;
|
||||
local($mod_map);
|
||||
$mod_map = {};
|
||||
&build_map( $name, $mod_map );
|
||||
return $mod_map;
|
||||
}
|
||||
|
||||
sub parse_modules {
|
||||
while( $l = &get_line ){
|
||||
($mod_name, $flag, @params) = split(/[ \t]+/,$l);
|
||||
if( $flag ne '-a' ){
|
||||
next;
|
||||
}
|
||||
$modules->{$mod_name} = [@params];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub build_map {
|
||||
local($name,$mod_map) = @_;
|
||||
local($bFound, $local);
|
||||
|
||||
$local = $NOT_LOCAL;
|
||||
$bFound = 0;
|
||||
|
||||
for $i ( @{$modules->{$name}} ){
|
||||
$bFound = 1;
|
||||
if( $i eq '-l' ){
|
||||
$local = $IS_LOCAL;
|
||||
}
|
||||
elsif( !build_map($i, $mod_map )){
|
||||
$mod_map->{$i} = $local;
|
||||
}
|
||||
}
|
||||
return $bFound;
|
||||
}
|
||||
|
||||
|
||||
|
||||
sub get_line {
|
||||
local($l, $save);
|
||||
|
||||
$bContinue = 1;
|
||||
|
||||
while( $bContinue && ($l = <MOD>) ){
|
||||
chop($l);
|
||||
if( $l =~ /^[ \t]*\#/
|
||||
|| $l =~ /^[ \t]*$/ ){
|
||||
$l='';
|
||||
}
|
||||
elsif( $l =~ /\\[ \t]*$/ ){
|
||||
chop ($l);
|
||||
$save .= $l . ' ';
|
||||
}
|
||||
elsif( $l eq '' && $save eq ''){
|
||||
# ignore blank lines
|
||||
}
|
||||
else {
|
||||
$bContinue = 0;
|
||||
}
|
||||
}
|
||||
return $save . $l;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,321 @@
|
|||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
# Query the CVS database.
|
||||
#
|
||||
require 'lloydcgi.pl';
|
||||
require 'cvsmenu.pl';
|
||||
require 'utils.pl';
|
||||
|
||||
|
||||
$|=1;
|
||||
|
||||
$CVS_ROOT = $form{"cvsroot"};
|
||||
|
||||
print "Content-type: text/html\n\n";
|
||||
|
||||
require 'modules.pl';
|
||||
|
||||
|
||||
EmitHtmlHeader("CVS Query Form", $CVS_ROOT);
|
||||
|
||||
|
||||
print "
|
||||
<p>
|
||||
<FORM METHOD=GET ACTION='cvsquery.cgi'>
|
||||
<p>
|
||||
<TABLE BORDER CELLPADDING=8 CELLSPACING=0>
|
||||
";
|
||||
|
||||
|
||||
#
|
||||
# module selector
|
||||
#
|
||||
print "
|
||||
<TR><TH ALIGN=RIGHT>Module:</TH>
|
||||
<TD>
|
||||
<SELECT name='module' size=5>
|
||||
";
|
||||
|
||||
|
||||
#
|
||||
# check to see if there are multple repositories
|
||||
#
|
||||
@reposList = &getRepositoryList();
|
||||
$bMultiRepos = (@reposList > 1);
|
||||
|
||||
#
|
||||
# This code sucks, I should rewrite it to be shorter
|
||||
#
|
||||
if( $form{module} eq 'all' || $form{module} eq '' ){
|
||||
print "<OPTION SELECTED VALUE='all'>All Files in the Repository\n";
|
||||
if( $bMultiRepos ){
|
||||
print "<OPTION VALUE='allrepositories'>All Files in all Repositories\n";
|
||||
}
|
||||
}
|
||||
elsif( $form{module} eq 'allrepositories' ){
|
||||
print "<OPTION VALUE='all'>All Files in the Repository\n";
|
||||
if( $bMultiRepos ){
|
||||
print "<OPTION SELECTED VALUE='allrepositories'>All Files in all Repositories\n";
|
||||
}
|
||||
}
|
||||
else {
|
||||
print "<OPTION VALUE='all'>All Files in the Repository\n";
|
||||
if( $bMultiRepos ){
|
||||
print "<OPTION VALUE='allrepositories'>All Files in all Repositories\n";
|
||||
}
|
||||
print "<OPTION SELECTED VALUE='$form{module}'>$form{module}\n";
|
||||
}
|
||||
|
||||
#
|
||||
# Print out all the Different Modules
|
||||
#
|
||||
for $k (sort( keys( %$modules ) ) ){
|
||||
print "<OPTION value='$k'>$k\n";
|
||||
}
|
||||
|
||||
print "</SELECT></td>\n";
|
||||
print "<td rowspan=2>";
|
||||
cvsmenu();
|
||||
print "</td></tr>";
|
||||
|
||||
#
|
||||
# Branch
|
||||
#
|
||||
if( defined $form{branch} ){
|
||||
$b = $form{branch};
|
||||
}
|
||||
else {
|
||||
$b = "HEAD";
|
||||
}
|
||||
print "<tr>
|
||||
<th align=right>Branch:</th>
|
||||
<td> <input type=text name=branch value='$b' size=25><br>\n" .
|
||||
regexpradio('branchtype') .
|
||||
"<br>(leaving this field empty will show you checkins on both
|
||||
<tt>HEAD</tt> and branches)
|
||||
</td></tr>";
|
||||
|
||||
#
|
||||
# Query by directory
|
||||
#
|
||||
print "
|
||||
<tr>
|
||||
<th align=right>Directory:</th>
|
||||
<td colspan=2>
|
||||
<input type=text name=dir value='$form{dir}' size=45><br>
|
||||
(you can list multiple directories)
|
||||
</td>
|
||||
</tr>
|
||||
";
|
||||
|
||||
print "
|
||||
<tr>
|
||||
<th align=right>File:</th>
|
||||
<td colspan=2>
|
||||
<input type=text name=file value='$form{file}' size=45><br>" .
|
||||
regexpradio('filetype') . "
|
||||
</td>
|
||||
</tr>
|
||||
";
|
||||
|
||||
|
||||
#
|
||||
# Who
|
||||
#
|
||||
print "
|
||||
<tr>
|
||||
<th align=right>Who:</th>
|
||||
<td colspan=2> <input type=text name=who value='$form{who}' size=45><br>" .
|
||||
regexpradio('whotype') . "
|
||||
</td>
|
||||
</tr>";
|
||||
|
||||
|
||||
#
|
||||
# Log contains
|
||||
#
|
||||
#print "
|
||||
#<br>
|
||||
#<nobr><b>Log contains:</b>
|
||||
#<input type=text name=logexpr size=45></nobr>(you can use <a href=cvsregexp.html>regular expressions</a>)\n";
|
||||
|
||||
|
||||
#
|
||||
# Sort order
|
||||
#
|
||||
print "
|
||||
<tr>
|
||||
<th align=right>Sort By:</th>
|
||||
<td colspan=2>
|
||||
<SELECT name='sortby'>
|
||||
<OPTION" . &sortTest("Date") . ">Date
|
||||
<OPTION" . &sortTest("Who") . ">Who
|
||||
<OPTION" . &sortTest("File") . ">File
|
||||
<OPTION" . &sortTest("Change Size") . ">Change Size
|
||||
</SELECT>
|
||||
</td>
|
||||
</tr>
|
||||
";
|
||||
|
||||
#
|
||||
# Print the date selector
|
||||
#
|
||||
|
||||
$CVS_REPOS_SUFFIX = $CVS_ROOT;
|
||||
$CVS_REPOS_SUFFIX =~ s:/:_:g;
|
||||
|
||||
$startdate = fetchCachedStartDate($CVS_ROOT);
|
||||
|
||||
if ($form{date} eq "") {
|
||||
$form{date} = "hours";
|
||||
}
|
||||
|
||||
print "
|
||||
<tr>
|
||||
<th align=right valign=top><br>Date:</th>
|
||||
<td colspan=2>
|
||||
<table BORDER=0 CELLSPACING=0 CELLPADDING=0>
|
||||
<tr>
|
||||
<td><input type=radio name=date " . &dateTest("hours") . "></td>
|
||||
<td>In the last <input type=text name=hours value=2 size=4> hours</td>
|
||||
</tr><tr>
|
||||
<td><input type=radio name=date " . &dateTest("day") . "></td>
|
||||
<td>In the last day</td>
|
||||
</tr><tr>
|
||||
<td><input type=radio name=date " . &dateTest("week") . "></td>
|
||||
<td>In the last week</td>
|
||||
</tr><tr>
|
||||
<td><input type=radio name=date " . &dateTest("month") . "></td>
|
||||
<td>In the last month</td>
|
||||
</tr><tr>
|
||||
<td><input type=radio name=date " . &dateTest("all") . "></td>
|
||||
<td>Since the beginning of time (which happens to be <TT><NOBR>$startdate</NOBR></TT> currently)</td>
|
||||
</tr><tr>
|
||||
<td><input type=radio name=date " . &dateTest("explicit") . "></td>
|
||||
<td><table BORDER=0 CELLPADDING=0 CELLPSPACING=0>
|
||||
<tr>
|
||||
<TD VALIGN=TOP ALIGN=RIGHT NOWRAP>
|
||||
Between <input type=text name=mindate value='$form{mindate}' size=25></td>
|
||||
<td valign=top rowspan=2>You can use the form
|
||||
<B><TT><NOBR>mm/dd/yy hh:mm:ss</NOBR></TT></B> or a Unix <TT>time_t</TT>
|
||||
(seconds since the Epoch.)
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td VALIGN=TOP ALIGN=RIGHT NOWRAP>
|
||||
and <input type=text name=maxdate '$form{maxdate}' size=25></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</tr>
|
||||
";
|
||||
|
||||
print "
|
||||
<tr>
|
||||
<th><BR></th>
|
||||
<td colspan=2>
|
||||
<INPUT TYPE=HIDDEN NAME=cvsroot VALUE='$CVS_ROOT'>
|
||||
<INPUT TYPE=SUBMIT VALUE='Run Query'>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</FORM>";
|
||||
|
||||
sub sortTest {
|
||||
if( $_[0] eq $form{sortby} ){
|
||||
return " SELECTED";
|
||||
}
|
||||
else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
refigureStartDateIfNecessary($CVS_ROOT);
|
||||
|
||||
sub dateTest {
|
||||
if( $_[0] eq $form{date} ){
|
||||
return " CHECKED value=$_[0]";
|
||||
}
|
||||
else {
|
||||
return "value=$_[0]";
|
||||
}
|
||||
}
|
||||
|
||||
sub regexpradio {
|
||||
my($name) = @_;
|
||||
my $useregexp = ($form{$name} eq 'regexp');
|
||||
my $c1 = $useregexp ? "" : "checked";
|
||||
my $c2 = $useregexp ? "checked" : "";
|
||||
return "
|
||||
<input type=radio name=$name value=match $c1>Exact match
|
||||
|
||||
<input type=radio name=$name value=regexp $c2><a href=cvsregexp.html>Regular expression</a>";
|
||||
}
|
||||
|
||||
|
||||
sub fetchCachedStartDate {
|
||||
my ($repository) = @_;
|
||||
open(CACHE, "<data/cachedstartdates") || return "unknown";
|
||||
while (<CACHE>) {
|
||||
chop();
|
||||
my($rep,$date,$cachedate) = split(/\|/);
|
||||
if ($rep eq $repository) {
|
||||
$rememberedcachedate = $cachedate;
|
||||
return $date;
|
||||
}
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
sub refigureStartDateIfNecessary {
|
||||
my ($repository) = @_;
|
||||
my $now = time();
|
||||
if ((defined $rememberedcachedate) &&
|
||||
$now - $rememberedcachedate < 24*60*60 &&
|
||||
$rememberedcachedate < $now) {
|
||||
return;
|
||||
}
|
||||
|
||||
my $db = ConnectToDatabase();
|
||||
|
||||
my $query = $db->Query("select min(when) from checkins,repositories where repositories.id = repositoryid and repository = '$CVS_ROOT'") || die $Mysql::db_errstr;
|
||||
|
||||
my @row = $query->fetchrow();
|
||||
my $startdate = $row[0];
|
||||
if ($startdate eq "") {
|
||||
$startdate = "nonexistant";
|
||||
}
|
||||
open(OUTCACHE, ">data/cachedstartdates.$$") || die "Can't open output date cache file";
|
||||
if (open(INCACHE, "<data/cachedstartdates")) {
|
||||
while (<INCACHE>) {
|
||||
chop();
|
||||
my($rep,$date,$cachedate) = split(/\|/);
|
||||
if ($rep ne $repository) {
|
||||
print OUTCACHE "$_\n";
|
||||
}
|
||||
}
|
||||
close INCACHE;
|
||||
}
|
||||
print OUTCACHE "$repository|$startdate|$now\n";
|
||||
close OUTCACHE;
|
||||
rename "data/cachedstartdates.$$", "data/cachedstartdates";
|
||||
}
|
|
@ -0,0 +1,257 @@
|
|||
<HTML>
|
||||
<HEAD>
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
|
||||
<META NAME="Author" CONTENT="lloyd tabb">
|
||||
<META NAME="GENERATOR" CONTENT="Mozilla/4.0 [en] (WinNT; I) [Netscape]">
|
||||
<TITLE>Regular expressions in the cvs query tool</TITLE>
|
||||
</HEAD>
|
||||
<BODY>
|
||||
|
||||
<H1>
|
||||
Description of MySQL regular expression syntax.</H1>
|
||||
Regular expressions are a powerful way of specifying complex searches.
|
||||
|
||||
<P><B>MySQL</B> uses regular Henry Spencers inplementation of regular expressions.
|
||||
And that is aimed to conform to POSIX 1003.2. <B>MySQL</B> uses the extended
|
||||
version.
|
||||
|
||||
<P>To get more exact information see Henry Spencers regex.7 manual.
|
||||
|
||||
<P>This is a simplistic reference that skips the details. From here on
|
||||
a regualr expressions is called a regexp.
|
||||
|
||||
<P>A regular expression describes a set of strings. The simplest case is
|
||||
one that has no special characters in it. For example the regexp <TT>hello</TT>
|
||||
matches <TT>hello</TT> and nothing else.
|
||||
|
||||
<P>Nontrivial regular expressions use certain special constructs so that
|
||||
they can match more than one string. For example, the regexp <TT>hello|word</TT>
|
||||
matches either the string <TT>hello</TT> or the string <TT>word</TT>.
|
||||
|
||||
<P>And a more comples example regexp <TT>B[an]*s</TT> matches any of the
|
||||
strings <TT>Bananas</TT>, <TT>Baaaaas</TT>, <TT>Bs</TT> and all other string
|
||||
starting with a <TT>B</TT> and continuing with any number of <TT>a</TT>
|
||||
<TT>n</TT> and ending with a <TT>s</TT>.
|
||||
|
||||
<P>The following special characters/constructs are known.
|
||||
<DL COMPACT>
|
||||
<DT>
|
||||
<TT>^</TT></DT>
|
||||
|
||||
<DD>
|
||||
Start of whole string.</DD>
|
||||
|
||||
<PRE>mysql> select "fo\nfo" regexp "^fo$"; -> 0
|
||||
mysql> select "fofo" regexp "^fo"; -> 1</PRE>
|
||||
|
||||
<DT>
|
||||
<TT>$</TT></DT>
|
||||
|
||||
<DD>
|
||||
End of whole string.</DD>
|
||||
|
||||
<PRE>mysql> select "fo\no" regexp "^fo\no$"; -> 1
|
||||
mysql> select "fo\no" regexp "^fo$"; -> 0</PRE>
|
||||
|
||||
<DT>
|
||||
<TT>.</TT></DT>
|
||||
|
||||
<DD>
|
||||
Any character (including newline).</DD>
|
||||
|
||||
<PRE>mysql> select "fofo" regexp "^f.*"; -> 1
|
||||
mysql> select "fo\nfo" regexp "^f.*"; -> 1</PRE>
|
||||
|
||||
<DT>
|
||||
<TT>a*</TT></DT>
|
||||
|
||||
<DD>
|
||||
Any sequence of zero or more a's.</DD>
|
||||
|
||||
<PRE>mysql> select "Ban" regexp "^Ba*n"; -> 1
|
||||
mysql> select "Baaan" regexp "^Ba*n"; -> 1
|
||||
mysql> select "Bn" regexp "^Ba*n"; -> 1</PRE>
|
||||
|
||||
<DT>
|
||||
<TT>a+</TT></DT>
|
||||
|
||||
<DD>
|
||||
Any sequence of one or more a's.</DD>
|
||||
|
||||
<PRE>mysql> select "Ban" regexp "^Ba+n"; -> 1
|
||||
mysql> select "Bn" regexp "^Ba+n"; -> 0</PRE>
|
||||
|
||||
<DT>
|
||||
<TT>a?</TT></DT>
|
||||
|
||||
<DD>
|
||||
Either zero or one a.</DD>
|
||||
|
||||
<PRE>mysql> select "Bn" regexp "^Ba?n"; -> 1
|
||||
mysql> select "Ban" regexp "^Ba?n"; -> 1
|
||||
mysql> select "Baan" regexp "^Ba?n"; -> 0</PRE>
|
||||
|
||||
<DT>
|
||||
<TT>de|abc</TT></DT>
|
||||
|
||||
<DD>
|
||||
Either the sequence <TT>de</TT> or <TT>abc</TT>.</DD>
|
||||
|
||||
<PRE>mysql> select "pi" regexp "pi|apa"; -> 1
|
||||
mysql> select "axe" regexp "pi|apa"; -> 0
|
||||
mysql> select "apa" regexp "pi|apa"; -> 1
|
||||
mysql> select "apa" regexp "^(pi|apa)$"; -> 1
|
||||
mysql> select "pi" regexp "^(pi|apa)$"; -> 1
|
||||
mysql> select "pix" regexp "^(pi|apa)$"; -> 0</PRE>
|
||||
|
||||
<DT>
|
||||
<TT>(abc)*</TT></DT>
|
||||
|
||||
<DD>
|
||||
Zero or more times the sequence <TT>abc</TT>.</DD>
|
||||
|
||||
<PRE>mysql> select "pi" regexp "^(pi)+$"; -> 1
|
||||
mysql> select "pip" regexp "^(pi)+$"; -> 0
|
||||
mysql> select "pipi" regexp "^(pi)+$"; -> 1</PRE>
|
||||
|
||||
<DT>
|
||||
<TT>{1}</TT></DT>
|
||||
|
||||
<DT>
|
||||
<TT>{2,3}</TT></DT>
|
||||
|
||||
<DD>
|
||||
The is a more general way of writing regexps that match many occurences.</DD>
|
||||
|
||||
<DL COMPACT>
|
||||
<DT>
|
||||
<TT>a*</TT></DT>
|
||||
|
||||
<DD>
|
||||
Can be written as <TT>a{0,}</TT>.</DD>
|
||||
|
||||
<DT>
|
||||
<TT>+</TT></DT>
|
||||
|
||||
<DD>
|
||||
Can be written as <TT>a{1,}</TT>.</DD>
|
||||
|
||||
<DT>
|
||||
<TT>?</TT></DT>
|
||||
|
||||
<DD>
|
||||
Can be written as <TT>a{0,1}</TT>.</DD>
|
||||
</DL>
|
||||
To be more precice an atom followed by a bound containing one integer <TT>i</TT>
|
||||
and no comma matches a sequence of exactly <TT>i</TT> matches of the atom.
|
||||
An atom followed by a bound containing one integer <TT>i</TT> and a comma
|
||||
matches a sequence of <TT>i</TT> or more matches of the atom. An atom followed
|
||||
by a bound containing two integers <TT>i</TT> and <TT>j</TT> matches a
|
||||
sequence of <TT>i</TT> through <TT>j</TT> (inclusive) matches of the atom.
|
||||
Both arguments must <TT>0 >= value <= RE_DUP_MAX (default 255)</TT>,
|
||||
and if there are two of them, the second must be bigger or equal to the
|
||||
first.
|
||||
<DT>
|
||||
<TT>[a-dX]</TT></DT>
|
||||
|
||||
<DT>
|
||||
<TT>[^a-dX]</TT></DT>
|
||||
|
||||
<DD>
|
||||
Any character which is (not if ^ is used) either <TT>a</TT>, <TT>b</TT>,
|
||||
<TT>c</TT>, <TT>d</TT> or <TT>X</TT>. To include <TT>]</TT> it has to be
|
||||
written first. To include <TT>-</TT> it has to be written first or last.
|
||||
So <TT>[0-9]</TT> matches any decimal digit. All character that does not
|
||||
have a defined mening inside a <TT>[]</TT> pair has no special meaning
|
||||
and matches only itself.</DD>
|
||||
|
||||
<PRE>mysql> select "aXbc" regexp "[a-dXYZ]"; -> 1
|
||||
mysql> select "aXbc" regexp "^[a-dXYZ]$"; -> 0
|
||||
mysql> select "aXbc" regexp "^[a-dXYZ]+$"; -> 1
|
||||
mysql> select "aXbc" regexp "^[^a-dXYZ]+$"; -> 0
|
||||
mysql> select "gheis" regexp "^[^a-dXYZ]+$"; -> 1
|
||||
mysql> select "gheisa" regexp "^[^a-dXYZ]+$"; -> 0</PRE>
|
||||
|
||||
<DT>
|
||||
<TT>[[.characters.]]</TT></DT>
|
||||
|
||||
<DD>
|
||||
The sequence of characters of that collating element. The sequence is a
|
||||
single element of the bracket expression's list. A bracket expression containing
|
||||
a multi-character collating element can thus match more than one character,
|
||||
e.g. if the collating sequence includes a <TT>ch</TT> collating element,
|
||||
then the RE <TT>[[.ch.]]*c</TT> matches the first five characters of <TT>chchcc</TT>.</DD>
|
||||
|
||||
<DT>
|
||||
<TT>[=character-class=]</TT></DT>
|
||||
|
||||
<DD>
|
||||
An equivalence class, standing for the sequences of characters of all collating
|
||||
elements equivalent to that one, including itself. For example, if <TT>o</TT>
|
||||
and <TT>(+)</TT> are the members of an equivalence class, then <TT>[[=o=]]</TT>,
|
||||
<TT>[[=(+)=]]</TT>, and <TT>[o(+)]</TT> are all synonymous. An equivalence
|
||||
class may not be an endpoint of a range.</DD>
|
||||
|
||||
<DT>
|
||||
<TT>[:character_class:]</TT></DT>
|
||||
|
||||
<DD>
|
||||
Within a bracket expression, the name of a character class enclosed in
|
||||
<TT>[:</TT> and <TT>:]</TT> stands for the list of all characters belonging
|
||||
to that class. Standard character class names are:</DD>
|
||||
|
||||
<TABLE BORDER WIDTH="100%" NOSAVE >
|
||||
<TR>
|
||||
<TD>alnum </TD>
|
||||
|
||||
<TD>digit </TD>
|
||||
|
||||
<TD>punct </TD>
|
||||
</TR>
|
||||
|
||||
<TR>
|
||||
<TD>alpha </TD>
|
||||
|
||||
<TD>graph </TD>
|
||||
|
||||
<TD>space </TD>
|
||||
</TR>
|
||||
|
||||
<TR>
|
||||
<TD>blank </TD>
|
||||
|
||||
<TD>lower </TD>
|
||||
|
||||
<TD>upper </TD>
|
||||
</TR>
|
||||
|
||||
<TR>
|
||||
<TD>cntrl </TD>
|
||||
|
||||
<TD>print </TD>
|
||||
|
||||
<TD>xdigit </TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
These stand for the character classes defined in ctype(3). A locale may
|
||||
provide others. A character class may not be used as an endpoint of a range.
|
||||
<PRE>mysql> select "justalnums" regexp "[[:alnum:]]+"; -> 1
|
||||
mysql> select "!!" regexp "[[:alnum:]]+"; -> 0</PRE>
|
||||
|
||||
<LI>
|
||||
[[:<:]]</LI>
|
||||
|
||||
<LI>
|
||||
[[:>:]] These match the null string at the beginning and end of a word
|
||||
respectively. A word is defined as a sequence of word characters which
|
||||
is neither preceded nor followed by word characters. A word character is
|
||||
an alnum character (as defined by ctype(3)) or an underscore.</LI>
|
||||
|
||||
<PRE>mysql> select "a word a" regexp "[[:<:]]word[[:>:]]"; -> 1
|
||||
mysql> select "a xword a" regexp "[[:<:]]word[[:>:]]"; -> 0</PRE>
|
||||
</DL>
|
||||
|
||||
<PRE>mysql> select "weeknights" regexp "^(wee|week)(knights|nights)$"; -> 1</PRE>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
|
@ -0,0 +1,963 @@
|
|||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
# cvsview.cgi - fake up some HTML based on RCS logs and diffs
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
# brendan and fur
|
||||
#
|
||||
# TODO in no particular order:
|
||||
# - Mocha-automate the main page's form so clicking on rev links in the table
|
||||
# change the default filename and revisions.
|
||||
# - Add a tab width input to the main page's form.
|
||||
# - Include log message in wasted horizontal real-estate of Shortcuts frame.
|
||||
# - Make old and new diff lines go to separate, side-by-side frames, and use
|
||||
# Mocha to slave their scrollbars together.
|
||||
# - Allow expansion of the top-level table to include the revision histories
|
||||
# of all the files in the directory.
|
||||
# - More more more xdiff/gdiff-like features...
|
||||
#
|
||||
|
||||
#
|
||||
# SRCROOTS is an array of repository roots under which to look for CVS files.
|
||||
#
|
||||
|
||||
# Figure out which directory bonsai is in by looking at argv[0]
|
||||
|
||||
$bonsaidir = $0;
|
||||
$bonsaidir =~ s:/[^/]*$::; # Remove last word, and slash before it.
|
||||
if ($bonsaidir eq '') {
|
||||
$bonsaidir = '.';
|
||||
}
|
||||
|
||||
chdir $bonsaidir || die "Couldn't chdir to $bonsaidir";
|
||||
require 'utils.pl';
|
||||
|
||||
loadConfigData();
|
||||
|
||||
NEXTTREE: foreach $i (@treelist) {
|
||||
$r = $treeinfo{$i}->{'repository'};
|
||||
foreach $j (@SRCROOTS) {
|
||||
if ($r eq $j) {
|
||||
next NEXTTREE;
|
||||
}
|
||||
}
|
||||
push @SRCROOTS, $r;
|
||||
}
|
||||
|
||||
|
||||
$MAX_REVS = 8;
|
||||
|
||||
#
|
||||
# Make sure both kinds of standard output go to STDOUT.
|
||||
# XXX dup stdout onto stderr and flush stdout after the following prints
|
||||
#
|
||||
# Until then, replace standard die built-in with our own.
|
||||
sub die {
|
||||
print 'fatal error: ';
|
||||
print @_;
|
||||
exit;
|
||||
}
|
||||
|
||||
# Consume one token from the already opened RCSFILE filehandle.
|
||||
# Unescape string tokens, if necessary.
|
||||
sub get_token {
|
||||
# Erase all-whitespace lines.
|
||||
while ($line_buffer =~ /^$/) {
|
||||
&die ('Unexpected EOF') if eof(RCSFILE);
|
||||
$line_buffer = <RCSFILE>;
|
||||
$line_buffer =~ s/^\s+//; # Erase leading whitespace
|
||||
}
|
||||
|
||||
# A string of non-whitespace characters is a token ...
|
||||
return $1 if ($line_buffer =~ s/^([^;@][^;\s]*)\s*//o);
|
||||
|
||||
# ...and so is a single semicolon ...
|
||||
return ';' if ($line_buffer =~ s/^;\s*//o);
|
||||
|
||||
# ...or an RCS-encoded string that starts with an @ character.
|
||||
$line_buffer =~ s/^@([^@]*)//o;
|
||||
$token = $1;
|
||||
|
||||
# Detect single @ character used to close RCS-encoded string.
|
||||
while ($line_buffer !~ /^@[^@]*$/o) {
|
||||
$token .= $line_buffer;
|
||||
&die ('Unexpected EOF') if eof(RCSFILE);
|
||||
$line_buffer = <RCSFILE>;
|
||||
}
|
||||
|
||||
# Retain the remainder of the line after the terminating @ character.
|
||||
($line_buffer) = ($line_buffer =~ /^@\s*([^@]*)/o);
|
||||
|
||||
# Undo escape-coding of @ characters.
|
||||
$token =~ s/@@/@/og;
|
||||
|
||||
return $token;
|
||||
}
|
||||
|
||||
# Consume a token from RCS filehandle and ensure that it matches
|
||||
# the given string constant.
|
||||
sub match_token {
|
||||
local ($match) = @_;
|
||||
|
||||
local ($token) = &get_token;
|
||||
&die ("Unexpected parsing error in RCS file.\n",
|
||||
"Expected token: $match, but saw: $token\n")
|
||||
if ($token ne $match);
|
||||
}
|
||||
|
||||
# Push RCS token back into the input buffer.
|
||||
sub unget_token {
|
||||
local ($token) = @_;
|
||||
$line_buffer = "$token $line_buffer";
|
||||
}
|
||||
|
||||
# Parses "administrative" header of RCS files, setting these globals:
|
||||
#
|
||||
# $head_revision -- Revision for which cleartext is stored
|
||||
# $principal_branch
|
||||
# $file_description
|
||||
# %revision_symbolic_name -- mapping from numerical revision # to symbolic tag
|
||||
# %tag_revision -- mapping from symbolic tag to numerical revision #
|
||||
#
|
||||
sub parse_rcs_admin {
|
||||
local ($token, $tag, $tag_name, $tag_revision);
|
||||
local (@tags);
|
||||
|
||||
# Undefine variables, because we may have already read another RCS file
|
||||
undef %tag_revision;
|
||||
undef %revision_symbolic_name;
|
||||
|
||||
while (1) {
|
||||
# Read initial token at beginning of line
|
||||
$token = &get_token(RCSFILE);
|
||||
|
||||
# We're done once we reach the description of the RCS tree
|
||||
if ($token =~ /^\d/o) {
|
||||
&unget_token($token);
|
||||
return;
|
||||
}
|
||||
|
||||
# print "token: $token\n";
|
||||
|
||||
if ($token eq 'head') {
|
||||
$head_revision = &get_token;
|
||||
&get_token; # Eat semicolon
|
||||
} elsif ($token eq 'branch') {
|
||||
$principal_branch = &get_token;
|
||||
&get_token; # Eat semicolon
|
||||
} elsif ($token eq 'symbols') {
|
||||
|
||||
# Create an associate array that maps from tag name to
|
||||
# revision number and vice-versa.
|
||||
while (($tag = &get_token) ne ';') {
|
||||
($tag_name, $tag_revision) = split(':', $tag);
|
||||
|
||||
$tag_revision{$tag_name} = $tag_revision;
|
||||
$revision_symbolic_name{$tag_revision} = $tag_name;
|
||||
}
|
||||
} elsif ($token eq 'comment') {
|
||||
$file_description = &get_token;
|
||||
&get_token; # Eat semicolon
|
||||
|
||||
# Ignore all these other fields - We don't care about them.
|
||||
} elsif (($token eq 'locks') ||
|
||||
($token eq 'strict') ||
|
||||
($token eq 'expand') ||
|
||||
($token eq 'access')) {
|
||||
(1) while (&get_token ne ';');
|
||||
} else {
|
||||
warn ("Unexpected RCS token: $token\n");
|
||||
}
|
||||
}
|
||||
|
||||
&die('Unexpected EOF');
|
||||
}
|
||||
|
||||
# Construct associative arrays that represent the topology of the RCS tree
|
||||
# and other arrays that contain info about individual revisions.
|
||||
#
|
||||
# The following associative arrays are created, keyed by revision number:
|
||||
# %revision_date -- e.g. "96.02.23.00.21.52"
|
||||
# %timestamp -- seconds since 12:00 AM, Jan 1, 1970 GMT
|
||||
# %revision_author -- e.g. "tom"
|
||||
# %revision_branches -- descendant branch revisions, separated by spaces,
|
||||
# e.g. "1.21.4.1 1.21.2.6.1"
|
||||
# %prev_revision -- revision number of previous *ancestor* in RCS tree.
|
||||
# Traversal of this array occurs in the direction
|
||||
# of the primordial (1.1) revision.
|
||||
# %prev_delta -- revision number of previous revision which forms the
|
||||
# basis for the edit commands in this revision.
|
||||
# This causes the tree to be traversed towards the
|
||||
# trunk when on a branch, and towards the latest trunk
|
||||
# revision when on the trunk.
|
||||
# %next_delta -- revision number of next "delta". Inverts %prev_delta.
|
||||
#
|
||||
# Also creates %last_revision, keyed by a branch revision number, which
|
||||
# indicates the latest revision on a given branch,
|
||||
# e.g. $last_revision{"1.2.8"} == 1.2.8.5
|
||||
#
|
||||
sub parse_rcs_tree {
|
||||
local($revision, $date, $author, $branches, $next);
|
||||
local($branch, $is_trunk_revision);
|
||||
|
||||
# Undefine variables, because we may have already read another RCS file
|
||||
undef %revision_date;
|
||||
undef %timestamp;
|
||||
undef %revision_author;
|
||||
undef %revision_branches;
|
||||
undef %prev_revision;
|
||||
undef %prev_delta;
|
||||
undef %next_delta;
|
||||
undef %last_revision;
|
||||
|
||||
while (1) {
|
||||
$revision = &get_token;
|
||||
|
||||
# End of RCS tree description ?
|
||||
if ($revision eq 'desc') {
|
||||
&unget_token($revision);
|
||||
return;
|
||||
}
|
||||
|
||||
$is_trunk_revision = ($revision =~ /^[0-9]+\.[0-9]+$/);
|
||||
|
||||
$tag_revision{$revision} = $revision;
|
||||
($branch) = $revision =~ /(.*)\.[0-9]+/o;
|
||||
$last_revision{$branch} = $revision;
|
||||
|
||||
# Parse date
|
||||
&match_token('date');
|
||||
$date = &get_token;
|
||||
$revision_date{$revision} = $date;
|
||||
&match_token(';');
|
||||
|
||||
# Convert date into timestamp
|
||||
# @date_fields = reverse(split(/\./, $date));
|
||||
# $date_fields[4]--; # Month ranges from 0-11, not 1-12
|
||||
# $timestamp{$revision} = &timegm(@date_fields);
|
||||
|
||||
# Parse author
|
||||
&match_token('author');
|
||||
$author = &get_token;
|
||||
$revision_author{$revision} = $author;
|
||||
&match_token(';');
|
||||
|
||||
# Parse state;
|
||||
&match_token('state');
|
||||
(1) while (&get_token ne ';');
|
||||
|
||||
# Parse branches
|
||||
&match_token('branches');
|
||||
$branches = '';
|
||||
while (($token = &get_token) ne ';') {
|
||||
$prev_revision{$token} = $revision;
|
||||
$prev_delta{$token} = $revision;
|
||||
$branches .= "$token ";
|
||||
}
|
||||
$revision_branches{$revision} = $branches;
|
||||
|
||||
# Parse revision of next delta in chain
|
||||
&match_token('next');
|
||||
$next = '';
|
||||
if (($token = &get_token) ne ';') {
|
||||
$next = $token;
|
||||
&get_token; # Eat semicolon
|
||||
$next_delta{$revision} = $next;
|
||||
$prev_delta{$next} = $revision;
|
||||
if ($is_trunk_revision) {
|
||||
$prev_revision{$revision} = $next;
|
||||
} else {
|
||||
$prev_revision{$next} = $revision;
|
||||
}
|
||||
}
|
||||
|
||||
if ($debug > 1) {
|
||||
print "revision = $revision\n";
|
||||
print "date = $date\n";
|
||||
print "author = $author\n";
|
||||
print "branches = $branches\n";
|
||||
print "next = $next\n\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Reads and parses complete RCS file from already-opened RCSFILE descriptor.
|
||||
sub parse_rcs_file {
|
||||
local ($file) = @_;
|
||||
&die("Couldn't open $file\n") if !open(RCSFILE, "< $file");
|
||||
$line_buffer = '';
|
||||
print "Reading RCS admin...\n" if ($debug);
|
||||
&parse_rcs_admin();
|
||||
print "Reading RCS revision tree topology...\n" if ($debug);
|
||||
&parse_rcs_tree();
|
||||
print "Done reading RCS file...\n" if ($debug);
|
||||
close(RCSFILE);
|
||||
}
|
||||
|
||||
# Map a tag to a numerical revision number. The tag can be a symbolic
|
||||
# branch tag, a symbolic revision tag, or an ordinary numerical
|
||||
# revision number.
|
||||
sub map_tag_to_revision {
|
||||
local($tag_or_revision) = @_;
|
||||
|
||||
local ($revision) = $tag_revision{$tag_or_revision};
|
||||
|
||||
# Is this a branch tag, e.g. xxx.yyy.0.zzz
|
||||
if ($revision =~ /(.*)\.0\.([0-9]+)/o) {
|
||||
$branch = $1 . '.' . $2;
|
||||
# Return latest revision on the branch, if any.
|
||||
return $last_revision{$branch} if (defined($last_revision{$branch}));
|
||||
return $1; # No revisions on branch - return branch point
|
||||
} else {
|
||||
return $revision;
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Print HTTP content-type header and the header-delimiting extra newline.
|
||||
#
|
||||
print "Content-type: text/html\n\n";
|
||||
|
||||
$request_method = $ENV{'REQUEST_METHOD'}; # e.g., "GET", "POST", etc.
|
||||
$script_name = $ENV{'SCRIPT_NAME'};
|
||||
$prefix = $script_name . $ENV{PATH_INFO} . '?'; # prefix for HREF= entries
|
||||
$query_string = $ENV{QUERY_STRING};
|
||||
|
||||
# Undo % URL-encoding
|
||||
while ($query_string =~ /(.*)\%([0-9a-fA-F][0-9a-fA-F])(.*)/) {
|
||||
# XXX - inefficient
|
||||
$query_string = $1 . pack('c', hex($2)) . $3;
|
||||
}
|
||||
|
||||
&die("REQUEST_METHOD 'GET' expected: got '$request_method'\n")
|
||||
if ($request_method ne 'GET');
|
||||
|
||||
# Default option values
|
||||
$opt_diff_mode = 'context';
|
||||
$opt_whitespace_mode = 'show';
|
||||
|
||||
# Parse options in URL. For example,
|
||||
# http://w3/cgi/cvsview.pl?subdir=foo&file=bar would assign
|
||||
# $opt_subdir = foo and $opt_file = bar.
|
||||
foreach $option (split(/&/, $query_string)) {
|
||||
&die("command $opt_command: garbled option $option\n")
|
||||
if ($option !~ /^([^=]+)=(.*)/);
|
||||
eval('$opt_' . $1 . '="' . $2 . '";');
|
||||
}
|
||||
|
||||
if( $opt_branch eq 'HEAD' ) { $opt_branch = ''; }
|
||||
|
||||
# Configuration colors for diff output.
|
||||
|
||||
$stable_bg_color = 'White';
|
||||
$skipping_bg_color = '#c0c0c0';
|
||||
$header_bg_color = 'Orange';
|
||||
$change_bg_color = 'LightBlue';
|
||||
$addition_bg_color = 'LightGreen';
|
||||
$deletion_bg_color = 'LightGreen';
|
||||
$diff_bg_color = 'White';
|
||||
|
||||
# Ensure that necessary arguments are present
|
||||
&die("command not defined in URL\n") if $opt_command eq '';
|
||||
&die("command $opt_command: subdir not defined\n") if $opt_subdir eq '';
|
||||
if ($opt_command eq 'DIFF' ||
|
||||
$opt_command eq 'DIFF_FRAMESET' ||
|
||||
$opt_command eq 'DIFF_LINKS') {
|
||||
&die("command $opt_command: file not defined in URL\n") if $opt_file eq '';
|
||||
&die("command $opt_command: rev1 not defined in URL\n") if $opt_rev1 eq '';
|
||||
&die("command $opt_command: rev2 not defined in URL\n") if $opt_rev2 eq '';
|
||||
}
|
||||
|
||||
# Propagate diff options to created links
|
||||
$prefix .= "diff_mode=$opt_diff_mode";
|
||||
$prefix .= "&whitespace_mode=$opt_whitespace_mode";
|
||||
$prefix .= "&root=$opt_root";
|
||||
|
||||
# Create a shorthand for the longest common initial substring of our URL.
|
||||
$magic_url = "$prefix&subdir=$opt_subdir";
|
||||
|
||||
# Now that we've munged QUERY_STRING into perl variables, set rcsdiff options.
|
||||
$rcsdiff = '/tools/ns/bin/rcsdiff -f';
|
||||
$rcsdiff .= ' -w' if ($opt_whitespace_mode eq 'ignore');
|
||||
|
||||
# Handle the "root" argument
|
||||
#
|
||||
if (defined($root = $opt_root) && $root ne '') {
|
||||
$root =~ s|/$||;
|
||||
if (-d $root) {
|
||||
unshift(@SRCROOTS, $root);
|
||||
} else {
|
||||
print "Error: Root, $root, is not a directory.<BR>\n";
|
||||
print "</BODY></HTML>\n";
|
||||
exit;
|
||||
}
|
||||
}
|
||||
foreach $root (@SRCROOTS) {
|
||||
$dir = "$root/$opt_subdir";
|
||||
if (-d $dir) {
|
||||
$found = 1;
|
||||
last;
|
||||
}
|
||||
}
|
||||
if (!$found) {
|
||||
print "<FONT SIZE=5><B>Error:</B> $opt_subdir not found in "
|
||||
.join(',', @SRCROOTS), "</FONT>\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
# Create top-level frameset document.
|
||||
sub do_diff_frameset {
|
||||
chdir($dir);
|
||||
|
||||
print "<TITLE>$opt_file: $opt_rev1 vs. $opt_rev2</TITLE>\n";
|
||||
print "<FRAMESET ROWS='*,90' FRAMESPACING=0 BORDER=1>\n";
|
||||
|
||||
print " <FRAME NAME=diff+$opt_file+$opt_rev1+$opt_rev2 ",
|
||||
" SRC=\"$magic_url&command=DIFF";
|
||||
print "&root=$opt_root" if defined($opt_root);
|
||||
print "&file=$opt_file&rev1=$opt_rev1&rev2=$opt_rev2\">\n";
|
||||
|
||||
print " <FRAME SRC=\"$magic_url&command=DIFF_LINKS";
|
||||
print "&root=$opt_root" if defined($opt_root);
|
||||
print "&file=$opt_file&rev1=$opt_rev1&rev2=$opt_rev2\">\n";
|
||||
print "</FRAMESET>\n";
|
||||
}
|
||||
|
||||
|
||||
# Create links to document created by DIFF command.
|
||||
sub do_diff_links {
|
||||
|
||||
chdir($dir);
|
||||
|
||||
open(RCSDIFF, "$rcsdiff -r$opt_rev1 -r$opt_rev2 $opt_file 2>/dev/null |");
|
||||
|
||||
print "<HEAD>\n";
|
||||
print "<SCRIPT LANGUAGE='JavaScript'>\n";
|
||||
print "var anchor = -1;\n\n";
|
||||
print "function nextAnchor() {\n",
|
||||
" if (anchor < parent.frames[0].document.anchors.length)\n",
|
||||
" parent.frames[0].location.hash = ++anchor;\n",
|
||||
"}\n\n";
|
||||
print "function prevAnchor() {\n",
|
||||
" if (anchor > 0)\n",
|
||||
" parent.frames[0].location.hash = --anchor;\n",
|
||||
"}\n";
|
||||
print "</SCRIPT>\n";
|
||||
print "</HEAD>";
|
||||
print "<BODY BGCOLOR=\"#FFFFFF\" TEXT=\"#000000\"";
|
||||
print " LINK=\"#0000EE\" VLINK=\"#551A8B\" ALINK=\"#FF0000\">\n";
|
||||
|
||||
print "<TITLE>$opt_file: $opt_rev1 vs. $opt_rev2</TITLE>\n";
|
||||
|
||||
print '<FORM><TABLE CELLPADDING=0 CELLSPACING=0 BORDER=0><TR VALIGN=TOP>';
|
||||
|
||||
my $lxr_base = "http://cvs-mirror.mozilla.org/webtools/lxr/source";
|
||||
my $diff_base = "cvsview2.cgi";
|
||||
my $blame_base = "cvsblame.cgi";
|
||||
|
||||
# total kludge!! lxr omits the top-level "mozilla" directory...
|
||||
my $lxr_path = "$opt_subdir/$opt_file";
|
||||
$lxr_path =~ s@^ns/@@;
|
||||
$lxr_path =~ s@^mozilla/@@;
|
||||
|
||||
my $lxr_link = "$lxr_base/$lxr_path";
|
||||
my $blame_link = "$blame_base?root=$CVS_ROOT\&file=$opt_subdir/$opt_file";
|
||||
my $diff_link = "$magic_url&command=DIRECTORY&file=$opt_file&rev1=$opt_rev1&rev2=$opt_rev2";
|
||||
$diff_link .= "&root=$opt_root" if defined($opt_root);
|
||||
|
||||
print "<TD NOWRAP ALIGN=LEFT VALIGN=CENTER>";
|
||||
print "<TABLE CELLPADDING=0 CELLSPACING=0 BORDER=0>";
|
||||
print "<TR><TD NOWRAP ALIGN=RIGHT VALIGN=TOP><A HREF=\"$diff_link\" TARGET=_top><B>diff:</B></A> </TD>";
|
||||
print "<TD NOWRAP>Change diff parameters.</TD></TR>\n";
|
||||
print "<TR><TD NOWRAP ALIGN=RIGHT VALIGN=TOP><A HREF=\"$blame_link\" TARGET=_top><B>blame:</B></A></TD>";
|
||||
print "<TD NOWRAP>Annotate line authors.</TD></TR>\n";
|
||||
print "<TR><TD NOWRAP ALIGN=RIGHT VALIGN=TOP><A HREF=\"$lxr_link\" TARGET=_top><B>lxr:</B></A> </TD>";
|
||||
print "<TD NOWRAP>Browse source as hypertext.</TD></TR>\n";
|
||||
print "</TABLE>";
|
||||
print "</TD>";
|
||||
|
||||
print "<TD WIDTH=8</TD>";
|
||||
|
||||
print "<TD>";
|
||||
print "<INPUT TYPE=button VALUE='Prev' ONCLICK='prevAnchor()'><BR>";
|
||||
print "<INPUT TYPE=button VALUE='Next' ONCLICK='nextAnchor()'>";
|
||||
print "</TD>";
|
||||
print "<TD WIDTH=8></TD>";
|
||||
|
||||
print "<TD><CODE>";
|
||||
|
||||
$anchor_num = 0;
|
||||
while (<RCSDIFF>) {
|
||||
# Get one command from the diff file
|
||||
if (/^(c|a)(\d+)/) {
|
||||
$line = $2;
|
||||
while (<RCSDIFF>) {
|
||||
last if /^\.$/;
|
||||
}
|
||||
} elsif (/^d(\d+)/) {
|
||||
$line = $1;
|
||||
} else {
|
||||
print "<FONT SIZE=5 COLOR=#ffffff><B>Internal error:</B>",
|
||||
" unknown command $_",
|
||||
" at $. in $opt_file $opt_rev1\n";
|
||||
}
|
||||
|
||||
print ' ' x (4 - length($line));
|
||||
print "<A TARGET='diff+$opt_file+$opt_rev1+$opt_rev2'",
|
||||
" HREF=$magic_url&command=DIFF";
|
||||
print "&root=$opt_root" if defined($opt_root);
|
||||
print "&file=$opt_file&rev1=$opt_rev1&rev2=$opt_rev2#$anchor_num",
|
||||
" ONCLICK='anchor = $anchor_num'>$line</A> ";
|
||||
$anchor_num++;
|
||||
}
|
||||
close(RCSDIFF);
|
||||
|
||||
print '</TD></TR></TABLE>';
|
||||
print "</FORM></BODY>\n";
|
||||
}
|
||||
|
||||
|
||||
# Default tab width, although it's frequently 4.
|
||||
$tab_width = 8;
|
||||
|
||||
sub next_tab_stop {
|
||||
local ($pos) = @_;
|
||||
|
||||
return int(($pos + $tab_width) / $tab_width) * $tab_width;
|
||||
}
|
||||
|
||||
#
|
||||
# Look for the magic emacs tab width comment, or for long lines with more
|
||||
# than 4 leading tabs in more than 50% of the lines that start with a tab.
|
||||
# In the latter case, set $tab_width to 4.
|
||||
#
|
||||
sub guess_tab_width {
|
||||
local ($opt_file) = @_;
|
||||
local ($found_tab_width) = 0;
|
||||
local ($many_tabs, $any_tabs) = (0, 0);
|
||||
|
||||
open(RCSFILE, "$opt_file");
|
||||
while (<RCSFILE>) {
|
||||
if (/tab-width: (\d)/) {
|
||||
$tab_width = $1;
|
||||
$found_tab_width = 1;
|
||||
last;
|
||||
}
|
||||
if (/^(\t+)/) {
|
||||
$many_tabs++ if (length($1) >= 4);
|
||||
$any_tabs++;
|
||||
}
|
||||
}
|
||||
if (!$found_tab_width && $many_tabs > $any_tabs / 2) {
|
||||
$tab_width = 4;
|
||||
}
|
||||
close(RCSFILE);
|
||||
}
|
||||
|
||||
# Create gdiff-like output.
|
||||
sub do_diff {
|
||||
|
||||
print "<HTML><HEAD>";
|
||||
print "<TITLE>$opt_file: $opt_rev1 vs. $opt_rev2</TITLE>\n";
|
||||
print "</HEAD>";
|
||||
print "<BODY BGCOLOR=\"$diff_bg_color\" TEXT=\"#000000\"";
|
||||
print " LINK=\"#0000EE\" VLINK=\"#551A8B\" ALINK=\"#FF0000\">";
|
||||
|
||||
chdir($dir);
|
||||
|
||||
local ($rcsfile) = "$opt_file,v";
|
||||
$rcsfile = "Attic/$opt_file,v" if (! -r $rcsfile);
|
||||
&guess_tab_width($rcsfile);
|
||||
|
||||
&html_diff($rcsfile, $opt_rev1, $opt_rev2);
|
||||
print "\n</BODY>\n";
|
||||
}
|
||||
|
||||
|
||||
# Show specified CVS log entry.
|
||||
sub do_log {
|
||||
|
||||
chdir($dir);
|
||||
|
||||
print "<TITLE>$opt_file: $opt_rev CVS log entry</TITLE>\n";
|
||||
print '<PRE>';
|
||||
open(RCSLOG, "rlog -r$opt_rev $opt_file |");
|
||||
|
||||
while (<RCSLOG>) {
|
||||
last if (/^revision $opt_rev$/);
|
||||
}
|
||||
|
||||
while (<RCSLOG>) {
|
||||
last if (/^===============================================/);
|
||||
print "$_<BR>";
|
||||
}
|
||||
close(RCSLOG);
|
||||
|
||||
print '</PRE>';
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Main script: generate a table of revision diff and log message hotlinks
|
||||
# for each modified file in $opt_subdir, and a form for choosing a file and any
|
||||
# two of its revisions.
|
||||
#
|
||||
sub do_directory {
|
||||
|
||||
$output = "<DIV ALIGN=LEFT>";
|
||||
|
||||
foreach $path (split('/',$opt_subdir)) {
|
||||
$link_path .= $path;
|
||||
$output .= "<A HREF='rview.cgi?dir=$link_path";
|
||||
$output .= "&cvsroot=$opt_root" if defined $opt_root;
|
||||
$output .= "&rev=$opt_branch" if $opt_branch;
|
||||
$output .= "' onmouseover='window.status=\"Browse $link_path\";"
|
||||
." return true;'>$path</A>/ ";
|
||||
$link_path .= '/';
|
||||
}
|
||||
chop ($output);
|
||||
|
||||
if ($opt_branch) {
|
||||
$output .= "<BR>Branch: $opt_branch";
|
||||
}
|
||||
$output .= "</DIV>";
|
||||
|
||||
EmitHtmlHeader("CVS Differences", $output);
|
||||
|
||||
chdir($dir);
|
||||
|
||||
print "<TABLE BORDER CELLPADDING=2>\n";
|
||||
|
||||
foreach $file (split(/\+/, $opt_files)) {
|
||||
local ($path) = "$dir/$file,v";
|
||||
$path = "$dir/Attic/$file,v" if (! -r $path);
|
||||
&parse_rcs_file($path);
|
||||
|
||||
my $lxr_base = "http://cvs-mirror.mozilla.org/webtools/lxr/source";
|
||||
|
||||
# total kludge!! lxr omits the top-level "mozilla" directory...
|
||||
my $lxr_path = "$opt_subdir/$file";
|
||||
$lxr_path =~ s@^ns/@@;
|
||||
$lxr_path =~ s@^mozilla/@@;
|
||||
|
||||
my $lxr_link = "$lxr_base/$lxr_path";
|
||||
|
||||
print "<TR><TD NOWRAP><B>";
|
||||
print "<A HREF=\"$lxr_link\">$file</A><BR>";
|
||||
print "<A HREF=\"cvslog.cgi?file=$opt_subdir/$file\">Change Log</A>\n";
|
||||
print "</B></TD>\n";
|
||||
|
||||
if ($opt_branch) {
|
||||
$first_rev = &map_tag_to_revision($opt_branch);
|
||||
&die("$0: error: -r: No such revision: $opt_branch\n")
|
||||
if ($first_rev eq '');
|
||||
} else {
|
||||
$first_rev = $head_revision;
|
||||
}
|
||||
|
||||
$skip = $opt_skip;
|
||||
$revs_remaining = $MAX_REVS;
|
||||
for ($rev = $first_rev; $rev; $rev = $prev) {
|
||||
$prev = $prev_revision{$rev};
|
||||
next if $skip-- > 0;
|
||||
if (!$revs_remaining--) {
|
||||
#print '<TD ROWSPAN=2 VALIGN=TOP>';
|
||||
print '<TD VALIGN=TOP>';
|
||||
print "<A HREF=$magic_url&command=DIRECTORY";
|
||||
print "&root=$opt_root" if defined($opt_root);
|
||||
print "&files=$opt_files&branch=$opt_branch&skip=", $opt_skip + $MAX_REVS, "><i>Prior revisions</i></A>", "</TD>\n";
|
||||
last;
|
||||
}
|
||||
|
||||
my $href_open = "";
|
||||
my $href_close = "";
|
||||
if ( $prev && $rev ) {
|
||||
$href_open = "<A HREF=$magic_url&command=DIFF_FRAMESET";
|
||||
$href_open .= "&root=$opt_root" if defined($opt_root);
|
||||
$href_open .= "&file=$file&rev1=$prev&rev2=$rev>";
|
||||
$href_close = "</A>";
|
||||
}
|
||||
print "<TD>$href_open$rev$href_close<BR>";
|
||||
print "$revision_author{$rev}</TD>";
|
||||
}
|
||||
|
||||
print "</TR>\n";
|
||||
|
||||
if (0) {
|
||||
print "<TR>\n";
|
||||
$skip = $opt_skip;
|
||||
$revs_remaining = $MAX_REVS;
|
||||
for ($rev = $first_rev; $rev; $rev = $prev_revision{$rev}) {
|
||||
next if $skip-- > 0;
|
||||
last if !$revs_remaining--;
|
||||
print "<TD><A HREF=$magic_url&command=LOG";
|
||||
print "root=$opt_root" if defined($opt_root);
|
||||
print "&file=$file&rev=$rev>$revision_author{$rev}</A>",
|
||||
"</TD>\n";
|
||||
}
|
||||
print "</TR>\n";}
|
||||
}
|
||||
|
||||
print "</TABLE><SPACER TYPE=VERTICAL SIZE=20>\n";
|
||||
print '<FORM METHOD=get>';
|
||||
print '<INPUT TYPE=hidden NAME=command VALUE=DIFF>';
|
||||
print "<INPUT TYPE=hidden NAME=subdir VALUE=$opt_subdir>";
|
||||
print '<FONT SIZE=+1><B>New Query:</B></FONT>';
|
||||
print '<UL><TABLE BORDER=1 CELLSPACING=0 CELLPADDING=7><TR><TD>';
|
||||
|
||||
|
||||
# pick something remotely sensible to put in the "Filename" field.
|
||||
my $file = $opt_file;
|
||||
if ( !$file && $opt_files ) {
|
||||
$file = $opt_files;
|
||||
$file =~ s@\+.*@@;
|
||||
}
|
||||
|
||||
print "\n<TABLE CELLPADDING=0 CELLSPACING=0><TR><TD>\n",
|
||||
'Filename:',
|
||||
'</TD><TD>',
|
||||
'<INPUT TYPE=text NAME=file VALUE="', $file, '" SIZE=40>',
|
||||
"\n</TD></TR><TR><TD>\n",
|
||||
|
||||
'Old version:',
|
||||
'</TD><TD>',
|
||||
'<INPUT TYPE=text NAME=rev1 VALUE="', $opt_rev1, '" SIZE=20>',
|
||||
"\n</TD></TR><TR><TD>\n",
|
||||
|
||||
'New version:',
|
||||
'</TD><TD>',
|
||||
'<INPUT TYPE=text NAME=rev2 VALUE="', $opt_rev2, '" SIZE=20>',
|
||||
"\n</TD></TR></TABLE>\n";
|
||||
print '<TABLE BORDER=0 CELLPADDING=5 WIDTH="100%"><TR><TD>',
|
||||
'<INPUT TYPE=radio NAME=whitespace_mode VALUE="show" CHECKED>',
|
||||
' Show Whitespace',
|
||||
'<BR><INPUT TYPE=radio NAME=whitespace_mode VALUE="ignore">',
|
||||
' Ignore Whitespace',
|
||||
'</TD><TD>',
|
||||
'<INPUT TYPE=radio NAME=diff_mode VALUE="context" CHECKED>',
|
||||
' Context Diffs',
|
||||
'<BR><INPUT TYPE=radio NAME=diff_mode VALUE="full">',
|
||||
' Full Source Diffs';
|
||||
print '</TD></TR></TABLE>';
|
||||
print "<INPUT TYPE=submit>\n";
|
||||
print '</TD></TR></TABLE></UL>';
|
||||
print "</FORM>\n";
|
||||
|
||||
&print_bottom;
|
||||
}
|
||||
|
||||
#
|
||||
# This function generates a gdiff-style, side-by-side display using HTML.
|
||||
# It requires two arguments, each of which must be an open filehandle.
|
||||
# The first filehandle, DIFF, must be a `diff -f` style output containing
|
||||
# commands to convert the contents of the second filehandle, OLDREV, into
|
||||
# a later version of OLDREV's file.
|
||||
#
|
||||
sub html_diff {
|
||||
local ($file, $rev1, $rev2) = @_;
|
||||
local ($old_line_num) = 1;
|
||||
|
||||
open(DIFF, "$rcsdiff -f -r$rev1 -r$rev2 $file 2>/dev/null |");
|
||||
open(OLDREV, "/tools/ns/bin/co -p$rev1 $file 2>/dev/null |");
|
||||
|
||||
$anchor_num = 0;
|
||||
|
||||
if ($ENV{'HTTP_USER_AGENT'} =~ /Win/) {
|
||||
$font_tag = "<PRE><FONT FACE='Lucida Console' SIZE=-1>";
|
||||
} else {
|
||||
# We don't want your stinking Windows font
|
||||
$font_tag = "<PRE>";
|
||||
}
|
||||
print "<TABLE BGCOLOR=$stable_bg_color "
|
||||
.'CELLPADDING=0 CELLSPACING=0 WIDTH="100%" COLS=2>';
|
||||
print "<TR BGCOLOR=$header_bg_color><TH>Version $rev1<TH>Version $rev2</TR>";
|
||||
while (<DIFF>) {
|
||||
$mark = 0;
|
||||
if (/^a(\d+)/) {
|
||||
$point = $1;
|
||||
&skip_to_line($point + 1, *OLDREV, *old_line_num);
|
||||
while (<DIFF>) {
|
||||
last if (/^\.$/);
|
||||
&print_row('', $stable_bg_color, $_, $addition_bg_color);
|
||||
}
|
||||
} elsif ((($point, $mark) = /^c(\d+) (\d+)$/) ||
|
||||
(($point) = /^c(\d+)$/)) {
|
||||
$mark = $point if (!$mark);
|
||||
&skip_to_line($point, *OLDREV, *old_line_num);
|
||||
while (<DIFF>) {
|
||||
last if (/^\.$/);
|
||||
if ($old_line_num <= $mark) {
|
||||
$old_line = <OLDREV>;
|
||||
$old_line_num++;
|
||||
} else {
|
||||
$old_line = ''
|
||||
}
|
||||
&print_row($old_line, $change_bg_color, $_, $change_bg_color);
|
||||
}
|
||||
while ($old_line_num <= $mark) {
|
||||
$old_line = <OLDREV>;
|
||||
$old_line_num++;
|
||||
&print_row($old_line, $change_bg_color, '', $change_bg_color);
|
||||
}
|
||||
} elsif ((($point, $mark) = /^d(\d+) (\d+)$/) ||
|
||||
(($point) = /^d(\d+)$/)) {
|
||||
$mark = $point if (!$mark);
|
||||
&skip_to_line($point, *OLDREV, *old_line_num);
|
||||
while ($old_line = <OLDREV>) {
|
||||
$old_line_num++;
|
||||
&print_row($old_line, $deletion_bg_color, '', $stable_bg_color);
|
||||
last if ($. == $mark);
|
||||
}
|
||||
} else {
|
||||
print "</TABLE><FONT SIZE=5 COLOR=#ffffff><B>Internal error:</B>",
|
||||
" unknown command $_",
|
||||
" at $. in $opt_file $opt_rev1\n";
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Print the remaining lines in the original file. These are lines that
|
||||
# were not modified in the later revision
|
||||
#
|
||||
local ($base_old_line_num) = $old_line_num;
|
||||
while ($old_line = <OLDREV>) {
|
||||
$old_line_num++;
|
||||
&print_row($old_line, $stable_bg_color, $old_line, $stable_bg_color)
|
||||
if ($opt_diff_mode eq 'full' ||
|
||||
$old_line_num <= $base_old_line_num + 5);
|
||||
}
|
||||
|
||||
# print "</FONT></PRE>\n";
|
||||
print "</TABLE></FONT>\n";
|
||||
|
||||
&print_bottom;
|
||||
|
||||
close(OLDREV);
|
||||
close(DIFF);
|
||||
}
|
||||
|
||||
sub skip_to_line {
|
||||
local ($line_num, *OLDREV, *old_line_num) = @_;
|
||||
local ($anchor_printed) = 0;
|
||||
local ($skip_line_printed) = ($line_num - $old_line_num <= 10);
|
||||
local ($base_old_line_num) = $old_line_num;
|
||||
|
||||
|
||||
while ($old_line_num < $line_num) {
|
||||
if (!$anchor_printed && $old_line_num >= $line_num - 10) {
|
||||
print "\n<A NAME=$anchor_num>";
|
||||
$anchor_printed = 1;
|
||||
}
|
||||
|
||||
if ($opt_diff_mode eq 'context' && !$skip_line_printed &&
|
||||
$line_num - 5 <= $old_line_num) {
|
||||
print "\n</TABLE>\n";
|
||||
print "<TABLE BGCOLOR=$stable_bg_color "
|
||||
.'CELLPADDING=0 CELLSPACING=0 WIDTH="100%" COLS=2>';
|
||||
print "<TR BGCOLOR=$skipping_bg_color><TD>",
|
||||
"<B>Skipping to line $old_line_num:</B><TD> ";
|
||||
$skip_line_printed = 1;
|
||||
}
|
||||
|
||||
$old_line = <OLDREV>;
|
||||
$old_line_num++;
|
||||
|
||||
&print_row($old_line, $stable_bg_color, $old_line, $stable_bg_color)
|
||||
if ($opt_diff_mode eq 'full' ||
|
||||
$old_line_num <= $base_old_line_num + 5 ||
|
||||
$line_num - 5 < $old_line_num);
|
||||
}
|
||||
|
||||
print "<A NAME=$anchor_num>" if (!$anchor_printed);
|
||||
print '</A>';
|
||||
$anchor_num++;
|
||||
}
|
||||
|
||||
sub print_cell {
|
||||
local ($line, $color) = @_;
|
||||
local ($i, $j, $k, $n);
|
||||
local ($c, $newline);
|
||||
|
||||
if ($color eq $stable_bg_color) {
|
||||
print "<TD>$font_tag";
|
||||
} else {
|
||||
print "<TD BGCOLOR=$color>$font_tag";
|
||||
}
|
||||
|
||||
while (($c = substr($line, -1)) && ($c eq "\n" || $c eq "\r")) {
|
||||
chop $line;
|
||||
}
|
||||
$n = length($line);
|
||||
$newline = '';
|
||||
for ($i = $j = 0; $i < $n; $i++) {
|
||||
$c = substr($line, $i, 1);
|
||||
if ($c eq "\t") {
|
||||
for ($k = &next_tab_stop($j); $j < $k; $j++) {
|
||||
$newline .= ' ';
|
||||
}
|
||||
} else {
|
||||
$newline .= $c;
|
||||
$j++;
|
||||
}
|
||||
}
|
||||
$newline =~ s/&/&/g;
|
||||
$newline =~ s/</</g;
|
||||
$newline =~ s/>/>/g;
|
||||
if (length($newline) <= 80) {
|
||||
$newline = sprintf("%-80.80s", $newline);
|
||||
} else {
|
||||
$newline =~ s/([^\n\r]{80})([^\n\r]*)/$1\n$2/g;
|
||||
}
|
||||
print $newline;
|
||||
}
|
||||
|
||||
sub print_row {
|
||||
local ($line1, $color1, $line2, $color2) = @_;
|
||||
print "\n<TR>";
|
||||
&print_cell($line1, $color1);
|
||||
&print_cell($line2, $color2);
|
||||
}
|
||||
|
||||
sub print_bottom {
|
||||
print <<__BOTTOM__;
|
||||
<P>
|
||||
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD>
|
||||
<HR>
|
||||
<TR><TD>
|
||||
<FONT SIZE=-1>
|
||||
Mail feedback and feature requests to <A HREF="mailto:slamm\@netscape.com?subject=About the cvs differences script">slamm</A>.
|
||||
</TABLE>
|
||||
</BODY>
|
||||
</HTML>
|
||||
__BOTTOM__
|
||||
} # print_bottom
|
||||
|
||||
|
||||
sub do_cmd {
|
||||
|
||||
if ($opt_command eq 'DIFF_FRAMESET') { do_diff_frameset; }
|
||||
elsif ($opt_command eq 'DIFF_LINKS') { do_diff_links; }
|
||||
elsif ($opt_command eq 'DIFF') { do_diff; }
|
||||
elsif ($opt_command eq 'LOG') { do_log; }
|
||||
elsif ($opt_command eq 'DIRECTORY') { do_directory; }
|
||||
else { print "invalid command \"$opt_command\"."; }
|
||||
exit;
|
||||
}
|
||||
|
||||
do_cmd;
|
|
@ -0,0 +1,131 @@
|
|||
#!/usr/bonsaitools/bin/mysqltcl
|
||||
# -*- Mode: tcl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
|
||||
source CGI.tcl
|
||||
source adminfuncs.tcl
|
||||
|
||||
puts "Content-type: text/html
|
||||
|
||||
"
|
||||
|
||||
CheckPassword $FORM(password)
|
||||
|
||||
Lock
|
||||
LoadCheckins
|
||||
|
||||
|
||||
|
||||
switch -exact -- $FORM(command) {
|
||||
close {
|
||||
AdminCloseTree [ParseTimeAndCheck [FormData closetimestamp]]
|
||||
|
||||
puts "
|
||||
<TITLE>Clang!</TITLE>
|
||||
<H1>The tree is now closed.</H1>
|
||||
Mail has been sent notifying \"the hook\" and anyone subscribed to
|
||||
bonsai-treeinterest.
|
||||
<P>
|
||||
<a href=\"mailto:clienteng?subject=The tree is now closed.\">Click here</a>
|
||||
to send e-mail about it to clienteng.
|
||||
"
|
||||
|
||||
}
|
||||
open {
|
||||
AdminOpenTree [ParseTimeAndCheck [FormData lastgood]] \
|
||||
[info exists FORM(doclear)]
|
||||
puts "
|
||||
<TITLE>The floodgates are open.</TITLE>
|
||||
<H1>The tree is now open.</H1>
|
||||
Mail has been sent notifying \"the hook\" and anyone subscribed to
|
||||
bonsai-treeinterest.
|
||||
<a href=\"mailto:clienteng?subject=The tree is now opened.\">Click here</a>
|
||||
to send e-mail about it to clienteng.
|
||||
"
|
||||
}
|
||||
tweaktimes {
|
||||
set lastgoodtimestamp [ParseTimeAndCheck [FormData lastgood]]
|
||||
set closetimestamp [ParseTimeAndCheck [FormData lastclose]]
|
||||
puts "
|
||||
<TITLE>Let's do the time warp again...</TITLE>
|
||||
<H1>Times have been tweaked.</H1>
|
||||
"
|
||||
Log "Times tweaked: lastgood is [MyFmtClock $lastgoodtimestamp], closetime is [MyFmtClock $closetimestamp]"
|
||||
}
|
||||
editmotd {
|
||||
LoadMOTD
|
||||
if {![cequal [FormData origmotd] $motd]} {
|
||||
puts "
|
||||
<TITLE>Oops!</TITLE>
|
||||
<H1>Someone else has been here!</H1>
|
||||
|
||||
It looks like somebody else has changed the message-of-the-day.
|
||||
Terry was too lazy to implement anything beyond detecting this
|
||||
condition. You'd best go start over -- go back to the top of Bonsai,
|
||||
look at the current message-of-the-day, and decide if you still
|
||||
want to make your edits."
|
||||
PutsTrailer
|
||||
exit
|
||||
}
|
||||
|
||||
MailDiffs "message-of-the-day" $motd [FormData motd]
|
||||
set motd [FormData motd]
|
||||
puts "
|
||||
<TITLE>New MOTD</TITLE>
|
||||
<H1>The message-of-the-day has been changed.</H1>
|
||||
"
|
||||
WriteMOTD
|
||||
Log "New motd: $motd"
|
||||
}
|
||||
changepassword {
|
||||
if {![cequal $FORM(newpassword) $FORM(newpassword2)]} {
|
||||
puts "
|
||||
<TITLE>Oops!</TITLE>
|
||||
<H1>Mismatch!</H1>
|
||||
The two passwords you typed didn't match. Click <b>Back</b> and try again."
|
||||
PutsTrailer
|
||||
exit
|
||||
}
|
||||
if {$FORM(doglobal)} {
|
||||
CheckGlobalPassword
|
||||
set outfile data/passwd
|
||||
} else {
|
||||
set outfile "[DataDir]/treepasswd"
|
||||
}
|
||||
set encoded [string trim [exec ./data/trapdoor $FORM(newpassword)]]
|
||||
set fid [open $outfile "w"]
|
||||
puts $fid $encoded
|
||||
close $fid
|
||||
catch {chmod 0777 $outfile}
|
||||
puts "
|
||||
<TITLE>Locksmithing complete.</TITLE>
|
||||
<H1>Password changed.</H1>
|
||||
The new password is now in effect."
|
||||
PutsTrailer
|
||||
exit
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PutsTrailer
|
||||
|
||||
WriteCheckins
|
||||
Unlock
|
||||
|
||||
exit
|
|
@ -0,0 +1,103 @@
|
|||
#!/usr/bonsaitools/bin/mysqltcl
|
||||
# -*- Mode: tcl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
source CGI.tcl
|
||||
|
||||
puts "Content-type: text/html
|
||||
|
||||
<HTML>"
|
||||
|
||||
CheckPassword $FORM(password)
|
||||
|
||||
Lock
|
||||
LoadCheckins
|
||||
|
||||
set busted 0
|
||||
|
||||
if {![info exists $FORM(id)]} {
|
||||
set busted 1
|
||||
} else {
|
||||
|
||||
upvar #0 $FORM(id) info
|
||||
|
||||
if {![info exists info(notes)]} {
|
||||
set info(notes) ""
|
||||
}
|
||||
|
||||
foreach i [lsort [array names info]] {
|
||||
if {![cequal [FormData "orig$i"] $info($i)]} {
|
||||
set busted 1
|
||||
set text "Key $i -- orig is [FormData "orig$i"], new is $info($i)"
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if {$busted} {
|
||||
Unlock
|
||||
puts "
|
||||
<TITLE>Oops!</TITLE>
|
||||
<H1>Someone else has been here!</H1>
|
||||
|
||||
It looks like somebody else has changed or deleted this checkin.
|
||||
Terry was too lazy to implement anything beyond detecting this
|
||||
condition. You'd best go start over -- go back to the list of
|
||||
checkins, look for this checkin again, and decide if you still want to
|
||||
make your edits."
|
||||
|
||||
PutsTrailer
|
||||
exit
|
||||
}
|
||||
|
||||
proc ParseTimeAndCheck {timestr} {
|
||||
if {[catch {set result [convertclock $timestr]}]} {
|
||||
puts "
|
||||
<TITLE>Time trap</TITLE>
|
||||
<H1>Can't grok the time</H1>
|
||||
You entered a time of <tt>$timestr</tt>, and I can't understand it. Please
|
||||
hit <B>Back</B> and try again."
|
||||
exit
|
||||
}
|
||||
return $result
|
||||
}
|
||||
|
||||
if {[info exists FORM(nukeit)]} {
|
||||
Log "A checkin for $info(person) has been nuked."
|
||||
} else {
|
||||
Log "A checkin for $info(person) has been modified."
|
||||
}
|
||||
|
||||
set info(date) [ParseTimeAndCheck [FormData datestring]]
|
||||
foreach i {person dir files notes treeopen log} {
|
||||
set info($i) [FormData $i]
|
||||
}
|
||||
|
||||
if {[info exists FORM(nukeit)]} {
|
||||
set w [lsearch -exact $checkinlist $FORM(id)]
|
||||
if {$w >= 0} {
|
||||
set checkinlist [lreplace $checkinlist $w $w]
|
||||
}
|
||||
}
|
||||
|
||||
WriteCheckins
|
||||
|
||||
puts "OK, the checkin has been changed."
|
||||
|
||||
PutsTrailer
|
||||
exit
|
|
@ -0,0 +1,74 @@
|
|||
#!/usr/bonsaitools/bin/mysqltcl
|
||||
# -*- Mode: tcl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
source CGI.tcl
|
||||
|
||||
puts "Content-type: text/html
|
||||
|
||||
"
|
||||
|
||||
CheckPassword $FORM(password)
|
||||
|
||||
|
||||
set filename $FORM(msgname)
|
||||
|
||||
set fullfilename [DataDir]/$filename
|
||||
|
||||
Lock
|
||||
|
||||
if {[file exists $fullfilename]} {
|
||||
set text [read_file $fullfilename]
|
||||
} else {
|
||||
set text {}
|
||||
}
|
||||
|
||||
if {![cequal [FormData origtext] $text]} {
|
||||
puts "
|
||||
<TITLE>Oops!</TITLE>
|
||||
<H1>Someone else has been here!</H1>
|
||||
|
||||
It looks like somebody else has changed this message while you were editing it.
|
||||
Terry was too lazy to implement anything beyond detecting this
|
||||
condition. You'd best go start over -- go back to the top of Bonsai,
|
||||
work your way back to editing the message, and decide if you still
|
||||
want to make your edits."
|
||||
PutsTrailer
|
||||
exit
|
||||
}
|
||||
|
||||
|
||||
set text [FormData text]
|
||||
set fid [open $fullfilename "w"]
|
||||
puts $fid $text
|
||||
catch {chmod 0666 $fullfilename }
|
||||
close $fid
|
||||
|
||||
|
||||
Log "$filename set to $text"
|
||||
|
||||
Unlock
|
||||
|
||||
puts "
|
||||
<TITLE>New $filename</TITLE>
|
||||
<H1>The file <b>$filename</b> has been changed.</H1>
|
||||
"
|
||||
|
||||
PutsTrailer
|
||||
|
||||
exit
|
|
@ -0,0 +1,83 @@
|
|||
#!/usr/bonsaitools/bin/mysqltcl
|
||||
# -*- Mode: tcl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
source CGI.tcl
|
||||
|
||||
Lock
|
||||
LoadWhiteboard
|
||||
|
||||
set oldvalue [FormData origwhite]
|
||||
|
||||
|
||||
if {![cequal $oldvalue $whiteboard]} {
|
||||
Unlock
|
||||
puts "Content-type: text/html
|
||||
|
||||
<TITLE>Error -- pen stolen.</TITLE>
|
||||
<H1>Someone else just changed the whiteboard.</H1>
|
||||
|
||||
Somebody else has changed what's on the whiteboard. Your changes will
|
||||
stomp over theirs.
|
||||
<P>
|
||||
The whiteboard now reads:
|
||||
<hr>
|
||||
<PRE VARIABLE>$whiteboard</PRE>
|
||||
<hr>
|
||||
If you really want to change the whiteboard to your text, click the button
|
||||
below. Or maybe you want to tweak your text first. Or you can forget it and
|
||||
go back to the beginning.
|
||||
|
||||
<FORM method=get action=\"doeditwhiteboard.cgi\">
|
||||
<INPUT TYPE=HIDDEN NAME=origwhite VALUE=\"[value_quote $whiteboard]\">
|
||||
|
||||
Change the free-for-all whiteboard:<br>
|
||||
<TEXTAREA NAME=whiteboard ROWS=10 COLS=70>[FormData whiteboard]</TEXTAREA><BR>
|
||||
<INPUT TYPE=SUBMIT VALUE=\"Change the Whiteboard\">
|
||||
</FORM>
|
||||
"
|
||||
PutsTrailer
|
||||
exit
|
||||
}
|
||||
|
||||
|
||||
set newwhiteboard [string trimright [FormData whiteboard]]
|
||||
|
||||
MailDiffs "whiteboard" $whiteboard $newwhiteboard
|
||||
|
||||
set whiteboard $newwhiteboard
|
||||
WriteWhiteboard
|
||||
|
||||
Unlock
|
||||
|
||||
puts "
|
||||
<TITLE>Where's my blue marker?</TITLE>
|
||||
<H1>The whiteboard has been changed.</H1>
|
||||
The whiteboard now reads:
|
||||
<hr>
|
||||
<PRE VARIABLE>$whiteboard</PRE>
|
||||
"
|
||||
|
||||
|
||||
|
||||
|
||||
Log "Whiteboard changed to be: $whiteboard"
|
||||
|
||||
PutsTrailer
|
||||
|
||||
exit
|
|
@ -0,0 +1,220 @@
|
|||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
$cvsroot = substr(<STDIN>, 0, -1);
|
||||
$flag_debug = 0;
|
||||
$flag_tagcmd = 0;
|
||||
$repository = substr(<STDIN>, 0, -1);
|
||||
$repository_tag = '';
|
||||
|
||||
@mailto=();
|
||||
@changed_files = ();
|
||||
@added_files = ();
|
||||
@removed_files = ();
|
||||
@log_lines = ();
|
||||
@outlist = ();
|
||||
|
||||
$STATE_NONE = 0;
|
||||
$STATE_CHANGED = 1;
|
||||
$STATE_ADDED = 2;
|
||||
$STATE_REMOVED = 3;
|
||||
$STATE_LOG = 4;
|
||||
|
||||
&process_args;
|
||||
|
||||
if ($flag_debug ){
|
||||
print STDERR "----------------------------------------------\n";
|
||||
print STDERR "LOGINFO:\n";
|
||||
print STDERR " pwd:" . `pwd` . "\n";
|
||||
print STDERR " Args @ARGV\n";
|
||||
print STDERR " CVSROOT: $cvsroot\n";
|
||||
print STDERR " Repository: $repository\n";
|
||||
print STDERR " mailto: @mailto\n";
|
||||
print STDERR "----------------------------------------------\n";
|
||||
}
|
||||
|
||||
if ($flag_tagcmd) {
|
||||
&process_tag_command;
|
||||
} else {
|
||||
&get_loginfo;
|
||||
&process_cvs_info;
|
||||
}
|
||||
|
||||
if( $flag_debug){
|
||||
print STDERR "----------------------------------------------\n";
|
||||
print STDERR @outlist;
|
||||
print STDERR "----------------------------------------------\n";
|
||||
}
|
||||
|
||||
&mail_notification;
|
||||
|
||||
0;
|
||||
|
||||
sub process_args {
|
||||
while (@ARGV) {
|
||||
$arg = shift @ARGV;
|
||||
|
||||
if ($arg eq '-d') {
|
||||
$flag_debug = 1;
|
||||
print STDERR "Debug turned on...\n";
|
||||
} elsif ($arg eq '-t') {
|
||||
$flag_tagcmd = 1;
|
||||
last; # Keep the rest in ARGV; they're handled later.
|
||||
} else {
|
||||
push(@mailto, $arg);
|
||||
}
|
||||
}
|
||||
if( $repository eq '' ){
|
||||
open( REP, "<CVS/Repository");
|
||||
$repository = <REP>;
|
||||
chop($repository);
|
||||
close(REP);
|
||||
}
|
||||
$repository =~ s:^$cvsroot/::;
|
||||
|
||||
if (!$flag_tagcmd) {
|
||||
if( open( REP, "<CVS/Tag") ) {
|
||||
$repository_tag = <REP>;
|
||||
chop($repository_tag);
|
||||
close(REP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub get_loginfo {
|
||||
|
||||
if( $flag_debug){
|
||||
print STDERR "----------------------------------------------\n";
|
||||
}
|
||||
|
||||
# Iterate over the body of the message collecting information.
|
||||
#
|
||||
$state = $STATE_NONE;
|
||||
while (<STDIN>) {
|
||||
chop; # Drop the newline
|
||||
|
||||
if (/^__BONSAI__SEPARATOR__MAGIC__$/) {
|
||||
last;
|
||||
}
|
||||
|
||||
if( $flag_debug){
|
||||
print STDERR "$_\n";
|
||||
}
|
||||
|
||||
if (/^In directory/) {
|
||||
next;
|
||||
}
|
||||
|
||||
if (/^Modified Files/) { $state = $STATE_CHANGED; next; }
|
||||
if (/^Added Files/) { $state = $STATE_ADDED; next; }
|
||||
if (/^Removed Files/) { $state = $STATE_REMOVED; next; }
|
||||
if (/^Log Message/) { $state = $STATE_LOG; next; }
|
||||
|
||||
s/^[ \t\n]+//; # delete leading whitespace
|
||||
s/[ \t\n]+$//; # delete trailing whitespace
|
||||
|
||||
if ($state == $STATE_CHANGED) { push(@changed_files, split); }
|
||||
if ($state == $STATE_ADDED) { push(@added_files, split); }
|
||||
if ($state == $STATE_REMOVED) { push(@removed_files, split); }
|
||||
if ($state == $STATE_LOG) { push(@log_lines, $_); }
|
||||
}
|
||||
|
||||
if( $flag_debug){
|
||||
print STDERR "----------------------------------------------\n"
|
||||
. "changed files: @changed_files\n"
|
||||
. "added files: @added_files\n"
|
||||
. "removed files: @removed_files\n";
|
||||
print STDERR "----------------------------------------------\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sub process_cvs_info {
|
||||
local($d,$fn,$rev,$mod_time,$sticky,$tag,$stat,@d,$rcsfile);
|
||||
$time = time;
|
||||
while( <STDIN> ){ # Parsing the Entries file, actually.
|
||||
chop;
|
||||
$fn = "";
|
||||
($d,$fn,$rev,$mod_time,$sticky,$tag) = split(/\//);
|
||||
$stat = 'C';
|
||||
for $i (@changed_files, "BEATME.NOW", @added_files ) {
|
||||
if( $i eq "BEATME.NOW" ){ $stat = 'A'; }
|
||||
if($i eq $fn ){
|
||||
$rcsfile = "$cvsroot/$repository/$fn,v";
|
||||
if( ! -r $rcsfile ){
|
||||
$rcsfile = "$cvsroot/$repository/Attic/$fn,v";
|
||||
}
|
||||
open(LOG, "/tools/ns/bin/rlog -N -r$rev $rcsfile |")
|
||||
|| print STDERR "dolog.pl: Couldn't run rlog\n";
|
||||
$username = "nobody";
|
||||
$lines_added = 0;
|
||||
$lines_removed = 0;
|
||||
while(<LOG>){
|
||||
if (/^date:.* author: ([^;]*);.*/) {
|
||||
$username = $1;
|
||||
if (/lines: \+([0-9]*) -([0-9]*)/) {
|
||||
$lines_added = $1;
|
||||
$lines_removed = $2;
|
||||
}
|
||||
}
|
||||
}
|
||||
close( LOG );
|
||||
push(@outlist, ("$stat|$time|$username|$cvsroot|$repository|$fn|$rev|$sticky|$tag|+$lines_added|-$lines_removed\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for $i (@removed_files) {
|
||||
push( @outlist, ("R|$time|$username|$cvsroot|$repository|$i|||$repository_tag\n"));
|
||||
}
|
||||
|
||||
push (@outlist, "LOGCOMMENT\n");
|
||||
push (@outlist, join("\n",@log_lines));
|
||||
push (@outlist, "\n:ENDLOGCOMMENT\n");
|
||||
}
|
||||
|
||||
|
||||
sub process_tag_command {
|
||||
local($str,$part,$time);
|
||||
$time = time;
|
||||
$str = "Tag|$cvsroot|$time";
|
||||
while (@ARGV) {
|
||||
$part = shift @ARGV;
|
||||
$str .= "|" . $part;
|
||||
}
|
||||
push (@outlist, ("$str\n"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
sub do_commitinfo {
|
||||
}
|
||||
|
||||
|
||||
|
||||
sub mail_notification {
|
||||
|
||||
my $filename = "data/temp.$$";
|
||||
open(OUT, ">$filename") || die "Couldn't open output file.";
|
||||
print OUT "dummy: line preteending to be mail headers\n\n";
|
||||
print OUT @outlist, "\n";
|
||||
close OUT;
|
||||
system "./addcheckin.tcl $filename";
|
||||
# rm $filename;
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
#!/usr/bonsaitools/bin/mysqltcl
|
||||
# -*- Mode: tcl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
source CGI.tcl
|
||||
|
||||
puts "Content-type: text/html
|
||||
|
||||
<HTML>"
|
||||
|
||||
CheckPassword $FORM(password)
|
||||
|
||||
Lock
|
||||
LoadCheckins
|
||||
|
||||
if {![info exists FORM(command)]} {
|
||||
set FORM(command) nocommand
|
||||
}
|
||||
|
||||
|
||||
set list {}
|
||||
|
||||
foreach i [array names FORM] {
|
||||
switch -glob -- $i {
|
||||
{checkin-*} {
|
||||
if {[lsearch -exact $checkinlist $i] >= 0} {
|
||||
lappend list $i
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
set origtree $treeid
|
||||
|
||||
switch -exact -- $FORM(command) {
|
||||
nuke {
|
||||
foreach i $list {
|
||||
set w [lsearch -exact $checkinlist $i]
|
||||
if {$w >= 0} {
|
||||
set checkinlist [lreplace $checkinlist $w $w]
|
||||
}
|
||||
}
|
||||
set what "deleted."
|
||||
}
|
||||
setopen {
|
||||
foreach i $list {
|
||||
upvar #0 $i info
|
||||
set info(treeopen) 1
|
||||
}
|
||||
set what "modified to be open."
|
||||
}
|
||||
|
||||
setclose {
|
||||
foreach i $list {
|
||||
upvar #0 $i info
|
||||
set info(treeopen) 0
|
||||
}
|
||||
set what "modified to be closed."
|
||||
}
|
||||
movetree {
|
||||
if {[cequal $treeid $FORM(desttree)]} {
|
||||
puts "<H1>Pick a different tree</H1>"
|
||||
puts "You attempted to move checkins into the tree that they're"
|
||||
puts "already in. Hit <b>Back</b> and try again."
|
||||
PutsTrailer
|
||||
exit
|
||||
}
|
||||
foreach i $list {
|
||||
set w [lsearch -exact $checkinlist $i]
|
||||
if {$w >= 0} {
|
||||
set checkinlist [lreplace $checkinlist $w $w]
|
||||
}
|
||||
}
|
||||
WriteCheckins
|
||||
unset checkinlist
|
||||
set treeid $FORM(desttree)
|
||||
unset batchid
|
||||
LoadCheckins
|
||||
LoadTreeConfig
|
||||
foreach i $list {
|
||||
lappend checkinlist $i
|
||||
}
|
||||
set what "moved to the $treeinfo($treeid,description) tree."
|
||||
}
|
||||
default {
|
||||
puts "<h1>No command selected</h1>"
|
||||
puts "You need to select one of the radio command buttons at the"
|
||||
puts "bottom. Hit <b>Back</b> and try again."
|
||||
PutsTrailer
|
||||
exit
|
||||
}
|
||||
}
|
||||
|
||||
WriteCheckins
|
||||
Unlock
|
||||
|
||||
puts "
|
||||
<H1>OK, done.</H1>
|
||||
The selected checkins have been $what"
|
||||
|
||||
set treeid $origtree
|
||||
|
||||
PutsTrailer
|
||||
exit
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
#!/usr/bonsaitools/bin/mysqltcl
|
||||
# -*- Mode: tcl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
source CGI.tcl
|
||||
|
||||
LoadCheckins
|
||||
|
||||
upvar #0 $FORM(id) info
|
||||
|
||||
puts "Content-type: text/html
|
||||
|
||||
<HTML>
|
||||
<TITLE>Say the magic word.</TITLE>
|
||||
<H1>Edit a checkin.</H1>
|
||||
|
||||
Congratulations, you have found the hidden edit-a-checkin feature. Of course,
|
||||
you need to know the magic word to do anything from here.
|
||||
|
||||
<P>
|
||||
|
||||
<FORM method=get action=\"doeditcheckin.cgi\">
|
||||
<TABLE>
|
||||
<tr>
|
||||
<td align=right><B>Password:</B></td>
|
||||
<td><INPUT NAME=password TYPE=password></td>
|
||||
</tr><tr>
|
||||
<td align=right><B>When:</B></td>
|
||||
<td><INPUT NAME=datestring VALUE=\"[value_quote [MyFmtClock $info(date)]]\">
|
||||
</td></tr>
|
||||
"
|
||||
|
||||
if {![info exists info(notes)]} {
|
||||
set info(notes) ""
|
||||
}
|
||||
|
||||
foreach i {person dir files notes} {
|
||||
puts "<tr><td align=right><B>$i:</B></td>"
|
||||
puts "<td><INPUT NAME=$i VALUE=\"[value_quote $info($i)]\"></td></tr>"
|
||||
}
|
||||
|
||||
proc CheckString {value} {
|
||||
if {$value} {
|
||||
return "CHECKED"
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
puts "
|
||||
<tr><td align=right><b>Tree state:</b></td>
|
||||
<td><INPUT TYPE=radio NAME=treeopen VALUE=1 [CheckString $info(treeopen)]>Open
|
||||
</td></tr><tr><td></td>
|
||||
<td><INPUT TYPE=radio NAME=treeopen VALUE=0 [CheckString [expr !$info(treeopen)]]>Closed
|
||||
</td></tr><tr>
|
||||
<td align=right valign=top><B>Log message:</B></td>
|
||||
<td><TEXTAREA NAME=log ROWS=10 COLS=80>$info(log)</TEXTAREA></td></tr>
|
||||
</table>
|
||||
<INPUT TYPE=CHECKBOX NAME=nukeit>Check this box to blow away this checkin entirely.<br>
|
||||
|
||||
<INPUT TYPE=SUBMIT VALUE=Submit>"
|
||||
|
||||
foreach i [lsort [array names info]] {
|
||||
puts "<INPUT TYPE=HIDDEN NAME=orig$i VALUE=\"[value_quote $info($i)]\">"
|
||||
}
|
||||
puts "<INPUT TYPE=HIDDEN NAME=id VALUE=\"[value_quote $FORM(id)]\">"
|
||||
|
||||
puts "<INPUT TYPE=HIDDEN NAME=treeid VALUE=\"[value_quote $treeid]\">"
|
||||
|
||||
|
||||
|
||||
puts "</TABLE></FORM>"
|
||||
|
||||
PutsTrailer
|
||||
|
||||
exit
|
|
@ -0,0 +1,99 @@
|
|||
#!/usr/bonsaitools/bin/mysqltcl
|
||||
# -*- Mode: tcl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
source CGI.tcl
|
||||
|
||||
|
||||
puts "Content-type: text/html
|
||||
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>We don't need no stinkin' HTML compose window</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Message editor</h1>"
|
||||
|
||||
set filename $FORM(msgname)
|
||||
|
||||
set fullfilename [DataDir]/$filename
|
||||
|
||||
if {[file exists $fullfilename]} {
|
||||
set text [read_file $fullfilename]
|
||||
} else {
|
||||
set text {}
|
||||
}
|
||||
|
||||
puts "
|
||||
Below is the template for the <b>$filename</b> message. Type the
|
||||
magic word and edit at will, but be careful to not break anything,
|
||||
especially around the headers.
|
||||
|
||||
The following magic symbols exist:
|
||||
|
||||
<table>"
|
||||
|
||||
proc PutDoc {name desc} {
|
||||
puts "<tr>"
|
||||
puts "<td align=right><tt><b>%$name%</b></tt></td>"
|
||||
puts "<td>Replaced by the $desc</td>"
|
||||
puts "</tr>"
|
||||
}
|
||||
|
||||
|
||||
switch -exact -- $filename {
|
||||
openmessage -
|
||||
closemessage {
|
||||
PutDoc name "username of the person getting mail"
|
||||
PutDoc dir "directory for this checkin"
|
||||
PutDoc files "list of files for this checkin"
|
||||
PutDoc log "log message for this checkin"
|
||||
PutDoc profile "profile for this user"
|
||||
}
|
||||
treeopened -
|
||||
treeopenedsamehook -
|
||||
treeclosed {
|
||||
PutDoc "hooklist" "comma-separated list of e-mail address of people on the hook"
|
||||
}
|
||||
default {
|
||||
puts "</table><P><font color=red>Uh, hey, this isn't a legal file for"
|
||||
puts "you to be editing here!</font>"
|
||||
PutsTrailer
|
||||
exit
|
||||
}
|
||||
}
|
||||
|
||||
puts "
|
||||
</TABLE>
|
||||
<FORM method=get action=\"doeditmessage.cgi\">
|
||||
<INPUT TYPE=HIDDEN NAME=treeid VALUE=$treeid>
|
||||
<B>Password:</B> <INPUT NAME=password TYPE=password> <BR>
|
||||
<INPUT TYPE=HIDDEN NAME=msgname VALUE=$filename>
|
||||
<INPUT TYPE=HIDDEN NAME=origtext VALUE=\"[value_quote $text]\">
|
||||
<TEXTAREA NAME=text ROWS=40 COLS=80>$text</TEXTAREA><BR>
|
||||
<INPUT TYPE=SUBMIT VALUE=\"Change this message\">
|
||||
</FORM>
|
||||
|
||||
"
|
||||
|
||||
|
||||
PutsTrailer
|
||||
|
||||
exit
|
|
@ -0,0 +1,45 @@
|
|||
#!/usr/bonsaitools/bin/mysqltcl
|
||||
# -*- Mode: tcl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
source CGI.tcl
|
||||
|
||||
LoadWhiteboard
|
||||
|
||||
puts "Content-type: text/html
|
||||
|
||||
<TITLE>Scritch, scritch.</TITLE>
|
||||
<FORM method=post action=\"doeditwhiteboard.cgi\">
|
||||
<INPUT TYPE=HIDDEN NAME=treeid VALUE=$treeid>
|
||||
<INPUT TYPE=HIDDEN NAME=origwhite VALUE=\"[value_quote $whiteboard]\">
|
||||
|
||||
The free-for-all whiteboard is a fine place to put notes of general
|
||||
and temporary interest about the tree. (Like, \"I'm checking in a bunch
|
||||
of nasty stuff; stay out of the tree until 3:30pm\".)
|
||||
|
||||
<P>
|
||||
|
||||
Change the free-for-all whiteboard:<br>
|
||||
<TEXTAREA NAME=whiteboard ROWS=10 COLS=70>$whiteboard</TEXTAREA><BR>
|
||||
<INPUT TYPE=SUBMIT VALUE=\"Change the Whiteboard\">
|
||||
</FORM>
|
||||
"
|
||||
|
||||
PutsTrailer
|
||||
|
||||
exit
|
|
@ -0,0 +1,672 @@
|
|||
# -*- Mode: tcl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
# What some of the global variables mean:
|
||||
# lastgoodtimestamp -- the timestamp when we last knew we had a good tree.
|
||||
# closetimestamp -- when the tree was closed. When we open, it probably
|
||||
# becomes the lastgoodtimestamp
|
||||
|
||||
|
||||
|
||||
set ldapserver directory.mcom.com
|
||||
# set ldapserver hoth.mcom.com
|
||||
set ldapport 389
|
||||
|
||||
|
||||
if {![info exists env(TZ)] || [cequal $env(TZ) ""]} {
|
||||
# Shouldn't have to do this! Something busted on warp, I think.
|
||||
set env(TZ) PST8PDT
|
||||
}
|
||||
|
||||
|
||||
# BUGSYSTEMEXPR is something that may be redefined in data/configdata, which
|
||||
# will define what to use in the replacement part of a regsub to quote bug
|
||||
# numbers that appear in the system.
|
||||
set BUGSYSTEMEXPR {<A HREF="http://scopus/bugsplat/show_bug.cgi?id=&">&</A>}
|
||||
set treeid {default}
|
||||
|
||||
proc NOTDEF {foo} {
|
||||
}
|
||||
|
||||
proc ConnectToDatabase {} {
|
||||
global mysqlhandle
|
||||
if {![info exists mysqlhandle]} {
|
||||
set mysqlhandle [mysqlconnect]
|
||||
mysqluse $mysqlhandle "bonsai"
|
||||
}
|
||||
}
|
||||
|
||||
proc SendSQL { str } {
|
||||
# puts $str
|
||||
global mysqlhandle errorInfo
|
||||
if {[catch {mysqlsel $mysqlhandle $str} errmsg]} {
|
||||
puts $str
|
||||
error "$errmsg - $str" $errorInfo
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
proc MoreSQLData {} {
|
||||
global mysqlhandle
|
||||
set result [mysqlresult $mysqlhandle "rows?"]
|
||||
return [expr ![cequal $result ""] && $result > 0]
|
||||
}
|
||||
|
||||
proc FetchSQLData {} {
|
||||
global mysqlhandle
|
||||
return [mysqlnext $mysqlhandle]
|
||||
}
|
||||
|
||||
proc SqlQuote {str} {
|
||||
regsub -all "'" $str "''" str
|
||||
#
|
||||
# This next line is quoting hell. One level of quoting comes from
|
||||
# the TCL interpreter, and another level comes from TCL's regular
|
||||
# expression parser. It really works out to "change every
|
||||
# backslash to two backslashes".
|
||||
regsub -all "\\\\" $str "\\\\\\\\" str
|
||||
|
||||
return $str
|
||||
}
|
||||
|
||||
|
||||
proc GetId {table field value} {
|
||||
global lastidcache
|
||||
if {[info exists lastidcache($table)]} {
|
||||
lassign lastidcache($table) cval id
|
||||
if {[cequal $value $cval]} {
|
||||
return $id
|
||||
}
|
||||
}
|
||||
set qvalue [SqlQuote $value]
|
||||
SendSQL "select id from $table where $field = '$qvalue'"
|
||||
set result [lindex [FetchSQLData] 0]
|
||||
if {[cequal $result ""]} {
|
||||
SendSQL "insert into $table ($field) values ('$qvalue')"
|
||||
SendSQL "select LAST_INSERT_ID()"
|
||||
set result [lindex [FetchSQLData] 0]
|
||||
}
|
||||
set lastidcache($table) [list $value $result]
|
||||
return $result
|
||||
}
|
||||
|
||||
|
||||
set lastdescription { }
|
||||
set lastdescriptionid 0
|
||||
proc AddToDatabase {lines desc} {
|
||||
global lastdescription lastdescriptionid
|
||||
if {[clength $desc] > 60000} {
|
||||
set desc [crange $desc 0 60000]
|
||||
}
|
||||
set desc [string trimright $desc]
|
||||
|
||||
if {[cequal $desc $lastdescription]} {
|
||||
set descid $lastdescriptionid
|
||||
} else {
|
||||
set descid {}
|
||||
}
|
||||
|
||||
set basequery "replace into checkins(type,when,whoid,repositoryid,dirid,"
|
||||
append basequery "fileid,revision,stickytag,branchid,addedlines,"
|
||||
append basequery "removedlines,descid) values ("
|
||||
foreach line [split $lines "\n"] {
|
||||
if {[cequal $line ""]} {
|
||||
continue
|
||||
}
|
||||
lassign [split $line "|"] chtype date name repository dir \
|
||||
file version sticky branch addlines removelines
|
||||
|
||||
regsub {^T} $branch {} branch
|
||||
regsub {/$} $dir {} dir
|
||||
if {[cequal $addlines ""]} {
|
||||
set addlines 0
|
||||
}
|
||||
if {[cequal $removelines ""]} {
|
||||
set removelines 0
|
||||
}
|
||||
if {[catch {set removelines [expr abs($removelines)]}]} {
|
||||
continue
|
||||
}
|
||||
if {[catch {set date [fmtclock $date {%Y-%m-%d %H:%M}]}]} {
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
if {[cequal $descid ""]} {
|
||||
set quoted [SqlQuote $desc]
|
||||
SendSQL "select distinct descid from checkins,descs where when = '$date' and descs.id = descid and descs.description = '$quoted'"
|
||||
if {![MoreSQLData]} {
|
||||
SendSQL "insert into descs (description) values ('$quoted')"
|
||||
SendSQL "select LAST_INSERT_ID()"
|
||||
}
|
||||
set descid [lindex [FetchSQLData] 0]
|
||||
set lastdescriptionid $descid
|
||||
set lastdescription $desc
|
||||
}
|
||||
|
||||
set query $basequery
|
||||
switch $chtype {
|
||||
"C" {
|
||||
append query "'Change'"
|
||||
}
|
||||
"A" {
|
||||
append query "'Append'"
|
||||
}
|
||||
"R" {
|
||||
append query "'Remove'"
|
||||
}
|
||||
default {
|
||||
append query "NULL"
|
||||
}
|
||||
}
|
||||
append query ",'$date'"
|
||||
append query ",[GetId people who $name]"
|
||||
append query ",[GetId repositories repository $repository]"
|
||||
append query ",[GetId dirs dir $dir]"
|
||||
append query ",[GetId files file $file]"
|
||||
append query ",'[SqlQuote $version]'"
|
||||
append query ",'[SqlQuote $sticky]'"
|
||||
append query ",[GetId branches branch $branch]"
|
||||
append query ",$addlines"
|
||||
append query ",$removelines"
|
||||
append query ",$descid)"
|
||||
SendSQL $query
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
proc assert {arg} {
|
||||
set result [uplevel 1 expr $arg]
|
||||
if {!$result} {
|
||||
error "Bad assertion $arg"
|
||||
}
|
||||
}
|
||||
set lockcount 0
|
||||
|
||||
|
||||
proc html_quote {var} {
|
||||
regsub -all {&} "$var" {\&} var
|
||||
regsub -all {<} "$var" {\<} var
|
||||
regsub -all {>} "$var" {\>} var
|
||||
return $var
|
||||
}
|
||||
|
||||
proc url_quote_char {c} {
|
||||
scan $c "%c" value
|
||||
if {$value <= 32 || [regexp {[ %=&?]} $c]} {
|
||||
return [format "%%%02x" $value]
|
||||
}
|
||||
return $c
|
||||
}
|
||||
|
||||
proc url_quote {var} {
|
||||
set result ""
|
||||
foreach c [split $var ""] {
|
||||
append result [url_quote_char $c]
|
||||
}
|
||||
return $result
|
||||
}
|
||||
|
||||
proc DataDir {} {
|
||||
global treeid
|
||||
if {[cequal $treeid "default"]} {
|
||||
return data
|
||||
} else {
|
||||
return data/$treeid
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
proc Lock {} {
|
||||
global lockcount lockfid
|
||||
if {$lockcount <= 0} {
|
||||
set lockcount 0
|
||||
if {[catch {set lockfid [open "data/lockfile" "a"]}]} {
|
||||
catch {mkdir data}
|
||||
catch {chmod 0777 data}
|
||||
set lockfid [open "data/lockfile" "a"]
|
||||
}
|
||||
flock -write $lockfid
|
||||
catch {chmod 0666 data/lockfile}
|
||||
}
|
||||
incr lockcount
|
||||
}
|
||||
|
||||
|
||||
proc Unlock {} {
|
||||
global lockcount lockfid
|
||||
incr lockcount -1
|
||||
if {$lockcount <= 0} {
|
||||
funlock $lockfid
|
||||
close $lockfid
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
proc LoadDirList {} {
|
||||
global legaldirs treeid treeinfo
|
||||
set legaldirs {}
|
||||
|
||||
if {![info exists treeinfo($treeid,repository)]} {
|
||||
LoadTreeConfig
|
||||
}
|
||||
|
||||
set modules $treeinfo($treeid,repository)/CVSROOT/modules
|
||||
set dirsfile [DataDir]/legaldirs
|
||||
|
||||
if {[file exists $modules]} {
|
||||
if {![file exists $dirsfile] ||
|
||||
[file mtime $dirsfile] < [file mtime $modules]} {
|
||||
catch {exec ./createlegaldirs.tcl $treeid}
|
||||
}
|
||||
}
|
||||
|
||||
Lock
|
||||
for_file line $dirsfile {
|
||||
lappend legaldirs $line
|
||||
}
|
||||
Unlock
|
||||
}
|
||||
|
||||
|
||||
proc PickNewBatchID {} {
|
||||
global batchid
|
||||
incr batchid
|
||||
Lock
|
||||
set fid [open [DataDir]/batchid "w"]
|
||||
puts $fid "set batchid $batchid"
|
||||
close $fid
|
||||
Unlock
|
||||
}
|
||||
|
||||
|
||||
|
||||
set readonly 0
|
||||
|
||||
proc LoadCheckins {} {
|
||||
global batchid treeopen checkinlist
|
||||
global lastgoodtimestamp closetimestamp
|
||||
assert {![info exists checkinlist]}
|
||||
Lock
|
||||
if {![info exists batchid]} {
|
||||
set filename "[DataDir]/batchid"
|
||||
if {![file exists $filename]} {
|
||||
set fid [open $filename "w"]
|
||||
chmod 0666 $filename
|
||||
puts $fid "set batchid 1"
|
||||
close $fid
|
||||
}
|
||||
uplevel #0 source $filename
|
||||
}
|
||||
set filename [DataDir]/batch-$batchid
|
||||
if {[file exists $filename]} {
|
||||
uplevel #0 source $filename
|
||||
}
|
||||
Unlock
|
||||
|
||||
if {![info exists checkinlist]} {
|
||||
set checkinlist {}
|
||||
}
|
||||
if {![info exists treeopen]} {
|
||||
set treeopen 1
|
||||
}
|
||||
foreach t {lastgoodtimestamp closetimestamp} {
|
||||
if {![info exists $t]} {
|
||||
set $t [convertclock "1/1/70"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
proc WriteCheckins {} {
|
||||
global batchid checkinlist treeopen readonly
|
||||
global lastgoodtimestamp closetimestamp
|
||||
if {$readonly} {
|
||||
puts "<P><B><font color=red>Can't write checkins file; not viewing"
|
||||
puts "current info.</font></b>"
|
||||
return
|
||||
}
|
||||
set filename [DataDir]/temp-[id process]
|
||||
set fid [open $filename "w"]
|
||||
chmod 0666 $filename
|
||||
# Hack to make person be an empty array:
|
||||
set person(xyzzy) 1
|
||||
unset person(xyzzy)
|
||||
foreach i {treeopen lastgoodtimestamp closetimestamp checkinlist} {
|
||||
puts $fid [list set $i [set $i]]
|
||||
}
|
||||
foreach c $checkinlist {
|
||||
upvar #0 $c info
|
||||
foreach i [lsort [array names info]] {
|
||||
puts $fid [list set [set c]($i) $info($i)]
|
||||
}
|
||||
set person($info(person)) 1
|
||||
}
|
||||
close $fid
|
||||
Lock
|
||||
set filedest [DataDir]/batch-$batchid
|
||||
if {[file exists $filedest]} {
|
||||
unlink $filedest
|
||||
}
|
||||
frename $filename $filedest
|
||||
|
||||
set fid [open $filename "w"]
|
||||
chmod 0666 $filename
|
||||
foreach i [lsort [array names person]] {
|
||||
puts $fid $i
|
||||
}
|
||||
puts $fid "bonsai-hookinterest@glacier"
|
||||
puts $fid "mcom.dev.client.build.busted"
|
||||
close $fid
|
||||
frename $filename [DataDir]/hooklist
|
||||
|
||||
Unlock
|
||||
}
|
||||
|
||||
|
||||
|
||||
proc ConstructMailTo {name subject} {
|
||||
return "<a href=\"mailto:$name?subject=$subject\">Send mail to $name</a>"
|
||||
}
|
||||
|
||||
|
||||
|
||||
proc Log {str} {
|
||||
Lock
|
||||
set filename "[DataDir]/logfile"
|
||||
set fid [open $filename "a"]
|
||||
catch {chmod 0666 $filename}
|
||||
puts $fid "[fmtclock [getclock] "%D %H:%M"] $str"
|
||||
close $fid
|
||||
Unlock
|
||||
}
|
||||
|
||||
|
||||
proc GenerateProfileHTML {name} {
|
||||
global ldapserver ldapport
|
||||
foreach i {
|
||||
{cn Name}
|
||||
{mail E-mail}
|
||||
{telephonenumber Phone}
|
||||
{pager Pager}
|
||||
{nscpcurcontactinfo {Contact Info}}
|
||||
} {
|
||||
lassign $i n t
|
||||
lappend namelist $n
|
||||
set title($n) $t
|
||||
set value($n) ""
|
||||
}
|
||||
|
||||
if {[catch {set fid [open "|./data/ldapsearch -b \"o=Netscape Communications Corp.,c=US\" -h $ldapserver -p $ldapport -s sub \"(mail=$name@netscape.com)\" $namelist" r]} errinfo]} {
|
||||
return "<B>Error -- Couldn't contact the directory server.</B><PRE>$errinfo</PRE>"
|
||||
}
|
||||
|
||||
set result "<TABLE>"
|
||||
|
||||
while {[gets $fid line] >= 0} {
|
||||
if {[regexp -- {^([a-z]*): (.*)$} $line foo n v]} {
|
||||
lappend value($n) $v
|
||||
}
|
||||
}
|
||||
|
||||
if {[catch {close $fid} errinfo]} {
|
||||
return "<B>Error -- problem running ldapsearch.</B><PRE>$errinfo</PRE>"
|
||||
}
|
||||
|
||||
foreach i $namelist {
|
||||
foreach v $value($i) {
|
||||
append result "<TR><TD align=right><B>$title($i):</B></TD>"
|
||||
append result "<TD>$v</TD></TR>"
|
||||
}
|
||||
}
|
||||
append result "</TABLE>"
|
||||
|
||||
return $result
|
||||
}
|
||||
|
||||
|
||||
proc MyFmtClock {time} {
|
||||
return [fmtclock $time "%D %T"]
|
||||
}
|
||||
|
||||
|
||||
proc LoadMOTD {} {
|
||||
global motd
|
||||
Lock
|
||||
set motd {}
|
||||
if {[file exists [DataDir]/motd]} {
|
||||
uplevel #0 source [DataDir]/motd
|
||||
}
|
||||
Unlock
|
||||
}
|
||||
|
||||
proc WriteMOTD {} {
|
||||
global motd
|
||||
Lock
|
||||
set fid [open [DataDir]/motd "w"]
|
||||
catch {chmod 0666 [DataDir]/motd}
|
||||
puts $fid [list set motd $motd]
|
||||
close $fid
|
||||
Unlock
|
||||
}
|
||||
|
||||
proc LoadWhiteboard {} {
|
||||
global whiteboard origwhiteboard
|
||||
set whiteboard {}
|
||||
Lock
|
||||
if {[file exists [DataDir]/whiteboard]} {
|
||||
set whiteboard [read_file [DataDir]/whiteboard]
|
||||
}
|
||||
Unlock
|
||||
set origwhiteboard $whiteboard
|
||||
}
|
||||
|
||||
|
||||
proc WriteWhiteboard {} {
|
||||
global whiteboard origwhiteboard
|
||||
if {![cequal $origwhiteboard $whiteboard]} {
|
||||
Lock
|
||||
set filename "[DataDir]/whiteboard"
|
||||
if {[file exists $filename]} {
|
||||
catch {unlink $filename}
|
||||
}
|
||||
set fid [open $filename w]
|
||||
puts $fid $whiteboard
|
||||
close $fid
|
||||
catch {chmod 0666 $filename}
|
||||
Unlock
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
proc LoadTreeConfig {} {
|
||||
global treelist treeinfo
|
||||
Lock
|
||||
set treelist {}
|
||||
catch {unset treeinfo}
|
||||
set filename data/configdata
|
||||
if {[file exists $filename]} {
|
||||
uplevel #0 source $filename
|
||||
}
|
||||
Unlock
|
||||
}
|
||||
|
||||
|
||||
proc Pluralize {str num} {
|
||||
if {$num == 1} {
|
||||
return $str
|
||||
} else {
|
||||
return "[set str]s"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
proc MailDiffs {name oldstr newstr} {
|
||||
if {[cequal $oldstr $newstr]} {
|
||||
return
|
||||
}
|
||||
set old "data/old[set name].[id process]"
|
||||
set new "data/new[set name].[id process]"
|
||||
set diffs data/diffs.[id process]
|
||||
set fid [open $old "w"]
|
||||
puts $fid $oldstr
|
||||
close $fid
|
||||
set fid [open $new "w"]
|
||||
puts $fid $newstr
|
||||
close $fid
|
||||
catch {exec diff -c -b $old $new > $diffs}
|
||||
set difftext [read_file $diffs]
|
||||
if {[clength $difftext] > 3} {
|
||||
set text "From: bonsai-daemon
|
||||
To: bonsai-messageinterest@glacier, mcom.dev.client.build.busted
|
||||
Subject: [SubjectTag] Changes made to $name
|
||||
Mime-Version: 1.0
|
||||
Content-Type: text/plain
|
||||
|
||||
$difftext
|
||||
"
|
||||
|
||||
exec /usr/lib/sendmail -t << $text
|
||||
}
|
||||
unlink $old
|
||||
unlink $new
|
||||
unlink $diffs
|
||||
}
|
||||
|
||||
|
||||
proc PrettyDelta {delta} {
|
||||
set result ""
|
||||
set oneday [expr 24*60*60]
|
||||
if {$delta > $oneday} {
|
||||
set numdays [$delta / $oneday]
|
||||
append result " $numdays day"
|
||||
if {$numdays > 1} {
|
||||
append result "s"
|
||||
}
|
||||
set delta [expr $delta % $oneday]
|
||||
}
|
||||
set onehour [expr 60*60]
|
||||
set numhours [expr $delta / $onehour]
|
||||
if {$numhours > 0} {
|
||||
append result " $numhours hour"
|
||||
if {$numhours > 1} {
|
||||
append result "s"
|
||||
}
|
||||
set delta [expr $delta % $onehour]
|
||||
}
|
||||
set oneminute 60
|
||||
set numminutes [expr $delta / $oneminute]
|
||||
if {$numminutes > 0} {
|
||||
append result " $numminutes minute"
|
||||
if {$numminutes > 1} {
|
||||
append result "s"
|
||||
}
|
||||
set delta [expr $delta % $oneminute]
|
||||
}
|
||||
if {$delta > 0} {
|
||||
append result " $delta second"
|
||||
if {$delta > 1} {
|
||||
append result "s"
|
||||
}
|
||||
}
|
||||
return $result
|
||||
}
|
||||
|
||||
|
||||
|
||||
# Generate a string to put at the head of a subject of an e-mail.
|
||||
proc SubjectTag {} {
|
||||
global treeid
|
||||
if {[cequal $treeid default]} {
|
||||
return {[Bonsai]}
|
||||
} else {
|
||||
return "\[Bonsai-$treeid\]"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Confirm that the given password is right. If not, generate HTML and exit.
|
||||
|
||||
proc CheckGlobalPassword {password {encoded {}}} {
|
||||
set fid [open data/passwd "r"]
|
||||
set correct [string trim [read $fid]]
|
||||
close $fid
|
||||
|
||||
if {[clength $encoded] == 0} {
|
||||
set encoded [string trim [exec ./data/trapdoor $password]]
|
||||
}
|
||||
|
||||
if {![cequal $correct $encoded]} {
|
||||
puts "<TITLE>Bzzzzt!</TITLE>"
|
||||
puts "<H1>Invalid password.</h1>"
|
||||
puts "Please click the <b>Back</b> button and try again."
|
||||
Log "Invalid admin password entered."
|
||||
exit
|
||||
}
|
||||
}
|
||||
|
||||
proc CheckPassword {password} {
|
||||
set encoded [string trim [exec ./data/trapdoor $password]]
|
||||
set f [DataDir]/treepasswd
|
||||
set correct "xxx $encoded"
|
||||
if {[file exists $f]} {
|
||||
set fid [open $f "r"]
|
||||
set correct [string trim [read $fid]]
|
||||
close $fid
|
||||
}
|
||||
|
||||
if {![cequal $correct $encoded]} {
|
||||
CheckGlobalPassword $password $encoded
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
proc ParseTimeAndCheck {timestr} {
|
||||
if {[catch {set result [convertclock $timestr]}]} {
|
||||
puts "
|
||||
<TITLE>Time trap</TITLE>
|
||||
<H1>Can't grok the time</H1>
|
||||
You entered a time of <tt>$timestr</tt>, and I can't understand it. Please
|
||||
hit <B>Back</B> and try again."
|
||||
exit
|
||||
}
|
||||
return $result
|
||||
}
|
||||
|
||||
|
||||
|
||||
proc MungeTagName {name} {
|
||||
set result ""
|
||||
foreach c [split $name ""] {
|
||||
scan $c "%c" value
|
||||
if {$value <= 32 || [regexp {[ %/?*]} $c]} {
|
||||
append result [format "%%%02x" $value]
|
||||
} else {
|
||||
append result $c
|
||||
}
|
||||
}
|
||||
return $result
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
#!/usr/bonsaitools/bin/mysqltcl
|
||||
# -*- Mode: tcl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
|
||||
# cd /u/terry/warproot/projects/bonsai
|
||||
cd /d/webdocs/projects/bonsai
|
||||
|
||||
set filename data/admin.[id process]
|
||||
|
||||
catch {unlink $filename}
|
||||
exec cat >> $filename
|
||||
catch {chmod 0666 $filename}
|
||||
exec ./adminmail.tcl $filename
|
||||
# unlink $filename
|
||||
|
||||
exit
|
|
@ -0,0 +1,61 @@
|
|||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
|
||||
sub EmitHtmlTitleAndHeader {
|
||||
my($doctitle,$heading,$subheading) = @_;
|
||||
|
||||
print "<HTML><HEAD><TITLE>$doctitle</TITLE></HEAD>";
|
||||
print "<BODY BGCOLOR=\"#FFFFFF\" TEXT=\"#000000\"";
|
||||
print "LINK=\"#0000EE\" VLINK=\"#551A8B\" ALINK=\"#FF0000\">";
|
||||
|
||||
if (open(BANNER, "<data/banner.html")) {
|
||||
while (<BANNER>) { print; }
|
||||
close BANNER;
|
||||
} elsif (open(BANNER, "<../bonsai/data/banner.html")) {
|
||||
while (<BANNER>) { print; }
|
||||
close BANNER;
|
||||
}
|
||||
|
||||
print "<TABLE BORDER=0 CELLPADDING=12 CELLSPACING=0 WIDTH=\"100%\">";
|
||||
print " <TR>\n";
|
||||
print " <TD>\n";
|
||||
print " <TABLE BORDER=0 CELLPADDING=0 CELLSPACING=2>\n";
|
||||
print " <TR><TD VALIGN=TOP ALIGN=CENTER NOWRAP>\n";
|
||||
print " <FONT SIZE=\"+3\"><B><NOBR>$heading</NOBR></B></FONT>\n";
|
||||
print " </TD></TR><TR><TD VALIGN=TOP ALIGN=CENTER>\n";
|
||||
print " <B>$subheading</B>\n";
|
||||
print " </TD></TR>\n";
|
||||
print " </TABLE>\n";
|
||||
print " </TD>\n";
|
||||
print " <TD>\n";
|
||||
|
||||
if (open(BLURB, "<data/blurb")) {
|
||||
while (<BLURB>) { print; }
|
||||
close BLURB;
|
||||
}
|
||||
|
||||
print "</TD></TR></TABLE>\n";
|
||||
}
|
||||
|
||||
sub EmitHtmlHeader {
|
||||
my($heading,$subheading) = @_;
|
||||
EmitHtmlTitleAndHeader($heading,$heading,$subheading);
|
||||
}
|
||||
|
||||
1;
|
|
@ -0,0 +1,12 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Refresh"
|
||||
content="0; URL=toplevel.cgi">
|
||||
</head>
|
||||
<body>
|
||||
Going to<br>
|
||||
<br>
|
||||
<a href="toplevel.cgi">toplevel.cgi</a>
|
||||
<br>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,44 @@
|
|||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
if( $ARGV[0] eq '' ){
|
||||
$CVS_ROOT = '/m/src';
|
||||
}
|
||||
else {
|
||||
$CVS_ROOT = $ARGV[0];
|
||||
}
|
||||
|
||||
$CVS_REPOS_SUFIX = $CVS_ROOT;
|
||||
$CVS_REPOS_SUFIX =~ s/\//_/g;
|
||||
|
||||
$CHECKIN_DATA_FILE = "data/checkinlog${CVS_REPOS_SUFIX}";
|
||||
$CHECKIN_INDEX_FILE = "data/index${CVS_REPOS_SUFIX}";
|
||||
|
||||
|
||||
open(INDEX , "<$CHECKIN_INDEX_FILE");
|
||||
open(CI, "<$CHECKIN_DATA_FILE") || die "could not open checkin data file\n";
|
||||
|
||||
while( <INDEX> ){
|
||||
chop;
|
||||
($o,$d) = split(/\|/);
|
||||
seek(CI, $o, 0);
|
||||
$line = <CI>;
|
||||
($j,$d1) = split(/\|/);
|
||||
print "$d|$d1\n";
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
%form = ();
|
||||
&split_cgi_args;
|
||||
1;
|
||||
|
||||
sub split_cgi_args {
|
||||
local (@args, $pair, $key, $value, $s);
|
||||
|
||||
if ($ENV{"REQUEST_METHOD"} eq 'POST') {
|
||||
$s .= $_ while (<>);
|
||||
}
|
||||
else {
|
||||
$s = $ENV{"QUERY_STRING"};
|
||||
}
|
||||
|
||||
$s =~ tr/+/ /;
|
||||
@args= split(/\&/, $s );
|
||||
|
||||
for $pair (@args) {
|
||||
($key, $value) = split(/=/, $pair);
|
||||
$key =~ s/%([a-fA-F0-9]{2})/pack("C", hex($1))/eg;
|
||||
$value =~ s/%([a-fA-F0-9]{2})/pack("C", hex($1))/eg;
|
||||
$form{$key} = $value;
|
||||
}
|
||||
|
||||
# extract the cookies from the HTTP_COOKIE environment
|
||||
%cookie_jar = split('[;=] *',$ENV{'HTTP_COOKIE'});
|
||||
}
|
||||
|
||||
sub make_cgi_args {
|
||||
local($k,$v,$ret);
|
||||
for $k (sort keys %form){
|
||||
$ret .= ($ret eq "" ? '?' : '&');
|
||||
$v = $form{$k};
|
||||
$ret .= &url_encode2($k);
|
||||
$ret .= '=';
|
||||
$ret .= &url_encode2($v);
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
sub url_encode2 {
|
||||
local( $s ) = @_;
|
||||
|
||||
$s =~ s/\%/\%25/g;
|
||||
$s =~ s/\=/\%3d/g;
|
||||
$s =~ s/\?/\%3f/g;
|
||||
$s =~ s/ /\%20/g;
|
||||
$s =~ s/\n/\%0a/g;
|
||||
$s =~ s/\r//g;
|
||||
$s =~ s/\"/\%22/g;
|
||||
$s =~ s/\'/\%27/g;
|
||||
$s =~ s/\|/\%7c/g;
|
||||
$s =~ s/\&/\%26/g;
|
||||
return $s;
|
||||
}
|
||||
|
||||
|
||||
@weekdays = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat');
|
||||
@months = ('Jan','Feb','Mar','Apr','May','Jun',
|
||||
'Jul','Aug','Sep','Oct','Nov','Dec');
|
||||
|
||||
sub toGMTString {
|
||||
local ($seconds) = $_[0];
|
||||
|
||||
local ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)
|
||||
= gmtime($seconds);
|
||||
$year += 1900;
|
||||
|
||||
sprintf('%s, %02d-%s-%d %02d:%02d:%02d GMT',
|
||||
$weekdays[$wday],$mday,$months[$mon],$year,$hour,$min,$sec);
|
||||
}
|
|
@ -0,0 +1,146 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
mysql > /dev/null 2>/dev/null << OK_ALL_DONE
|
||||
|
||||
use bonsai;
|
||||
|
||||
drop table descs;
|
||||
drop table checkins;
|
||||
drop table people;
|
||||
drop table repositories;
|
||||
drop table dirs;
|
||||
drop table files;
|
||||
drop table branches;
|
||||
drop table tags;
|
||||
OK_ALL_DONE
|
||||
|
||||
|
||||
|
||||
mysql << OK_ALL_DONE
|
||||
use bonsai;
|
||||
create table descs (
|
||||
id mediumint not null auto_increment primary key,
|
||||
description text
|
||||
);
|
||||
|
||||
show columns from descs;
|
||||
show index from descs;
|
||||
|
||||
create table people (
|
||||
id mediumint not null auto_increment primary key,
|
||||
who varchar(16) not null,
|
||||
|
||||
unique(who)
|
||||
);
|
||||
|
||||
show columns from people;
|
||||
show index from people;
|
||||
|
||||
|
||||
create table repositories (
|
||||
id mediumint not null auto_increment primary key,
|
||||
repository varchar(64) not null,
|
||||
|
||||
unique(repository)
|
||||
);
|
||||
|
||||
show columns from repositories;
|
||||
show index from repositories;
|
||||
|
||||
|
||||
|
||||
create table dirs (
|
||||
id mediumint not null auto_increment primary key,
|
||||
dir varchar(128) not null,
|
||||
|
||||
unique(dir)
|
||||
);
|
||||
|
||||
show columns from dirs;
|
||||
show index from dirs;
|
||||
|
||||
|
||||
create table files (
|
||||
id mediumint not null auto_increment primary key,
|
||||
file varchar(128) not null,
|
||||
|
||||
unique(file)
|
||||
);
|
||||
|
||||
show columns from files;
|
||||
show index from files;
|
||||
|
||||
|
||||
|
||||
create table branches (
|
||||
id mediumint not null auto_increment primary key,
|
||||
branch varchar(64) not null,
|
||||
|
||||
unique(branch)
|
||||
);
|
||||
|
||||
show columns from branches;
|
||||
show index from branches;
|
||||
|
||||
|
||||
|
||||
create table checkins (
|
||||
type enum('Change', 'Add', 'Remove'),
|
||||
when datetime not null,
|
||||
whoid mediumint not null,
|
||||
repositoryid mediumint not null,
|
||||
dirid mediumint not null,
|
||||
fileid mediumint not null,
|
||||
revision varchar(32) not null,
|
||||
stickytag varchar(255) not null,
|
||||
branchid mediumint not null,
|
||||
addedlines int not null,
|
||||
removedlines int not null,
|
||||
descid mediumint,
|
||||
|
||||
unique (repositoryid,dirid,fileid,revision),
|
||||
index(when),
|
||||
index(whoid),
|
||||
index(repositoryid),
|
||||
index(dirid),
|
||||
index(fileid),
|
||||
index(branchid)
|
||||
);
|
||||
|
||||
show columns from checkins;
|
||||
show index from checkins;
|
||||
|
||||
|
||||
create table tags (
|
||||
repositoryid mediumint not null,
|
||||
branchid mediumint not null,
|
||||
dirid mediumint not null,
|
||||
fileid mediumint not null,
|
||||
revision varchar(32) not null,
|
||||
|
||||
unique(repositoryid,dirid,fileid,branchid,revision),
|
||||
index(repositoryid),
|
||||
index(dirid),
|
||||
index(fileid),
|
||||
index(branchid)
|
||||
);
|
||||
|
||||
|
||||
|
||||
OK_ALL_DONE
|
|
@ -0,0 +1,134 @@
|
|||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
|
||||
#
|
||||
# Unroll a module
|
||||
#
|
||||
require 'lloydcgi.pl';
|
||||
require 'cvsmenu.pl';
|
||||
|
||||
$|=1;
|
||||
|
||||
$CVS_ROOT = $form{"cvsroot"};
|
||||
|
||||
print "Content-type: text/html
|
||||
|
||||
<HTML>";
|
||||
|
||||
require 'modules.pl';
|
||||
|
||||
print "
|
||||
<HEAD>
|
||||
<TITLE>CVS Module Analyzer</TITLE>
|
||||
</HEAD>";
|
||||
|
||||
cvsmenu("align=right width=20%");
|
||||
|
||||
print "
|
||||
<H1>CVS Module Analyzer</H1>
|
||||
<p><b>This tool will show you the directories and files that make up a given
|
||||
cvs module.</b>
|
||||
";
|
||||
|
||||
|
||||
print "
|
||||
<p>
|
||||
<FORM METHOD=GET ACTION='moduleanalyse.cgi'>
|
||||
";
|
||||
|
||||
|
||||
#
|
||||
# module selector
|
||||
#
|
||||
print "
|
||||
|
||||
<nobr><b>Module:</b>
|
||||
<SELECT name='module' size=5>
|
||||
";
|
||||
|
||||
if( $form{module} eq 'all' || $form{module} eq '' ){
|
||||
print "<OPTION SELECTED VALUE='all'>All Files in the Repository\n";
|
||||
}
|
||||
else {
|
||||
print "<OPTION VALUE='all'>All Files in the Repository\n";
|
||||
print "<OPTION SELECTED VALUE='$form{module}'>$form{module}\n";
|
||||
}
|
||||
|
||||
#
|
||||
# Print out all the Different Modules
|
||||
#
|
||||
for $k (sort( keys( %$modules ) ) ){
|
||||
print "<OPTION value='$k'>$k\n";
|
||||
}
|
||||
|
||||
print "</SELECT></NOBR>\n";
|
||||
|
||||
|
||||
print "
|
||||
<br>
|
||||
<br>
|
||||
<INPUT TYPE=HIDDEN NAME=cvsroot VALUE='$CVS_ROOT'>
|
||||
<INPUT TYPE=SUBMIT VALUE='Examine Module'>
|
||||
</FORM>";
|
||||
|
||||
|
||||
if( $form{module} ne '' ){
|
||||
$mod = $form{module};
|
||||
print "<h1>Examining Module '$mod'</h1>\n\n";
|
||||
$mod_map = &get_module_map( $mod );
|
||||
for $i (sort keys %$mod_map) {
|
||||
if( -d "$CVS_ROOT/$i"){
|
||||
print "<dt><tt>Dir: </tt>";
|
||||
print "<a href=rview.cgi?dir=$i&cvsroot=$CVS_ROOT>$i</a>";
|
||||
}
|
||||
elsif ( -r "$CVS_ROOT/$i,v" ){
|
||||
print "<dt><font color=blue><tt>File: </tt></font>";
|
||||
print "<a href=cvsblame.cgi?file=$i&root=$CVS_ROOT>$i</a>";
|
||||
}
|
||||
else {
|
||||
print "<dt><font color=red><tt>Error: </tt></font>";
|
||||
print "$i : Not a file or a directory.";
|
||||
}
|
||||
|
||||
if( $mod_map->{$i} == $IS_LOCAL ){
|
||||
print "<font color=blue><tt> LOCAL</tt></font>";
|
||||
}
|
||||
print "\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub sortTest {
|
||||
if( $_[0] eq $form{sortby} ){
|
||||
return " SELECTED";
|
||||
}
|
||||
else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
sub dateTest {
|
||||
if( $_[0] eq $form{date} ){
|
||||
return " CHECKED value=$_[0]";
|
||||
}
|
||||
else {
|
||||
return "value=$_[0]";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,152 @@
|
|||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
require 'utils.pl';
|
||||
|
||||
$NOT_LOCAL = 1;
|
||||
$IS_LOCAL = 2;
|
||||
|
||||
$modules = {};
|
||||
|
||||
if( $CVS_ROOT eq "" ){
|
||||
$CVS_ROOT = pickDefaultRepository();
|
||||
}
|
||||
|
||||
if( $ENV{"OS"} eq "Windows_NT" ){
|
||||
$CVS_MODULES='modules';
|
||||
}
|
||||
else {
|
||||
$CVS_MODULES="${CVS_ROOT}/CVSROOT/modules";
|
||||
}
|
||||
|
||||
open( MOD, "<$CVS_MODULES") || die "can't open $CVS_MODULES";
|
||||
&parse_modules;
|
||||
close( MOD );
|
||||
|
||||
1;
|
||||
|
||||
sub in_module {
|
||||
local($mod_map, $dirname, $filename ) = @_;
|
||||
local( @path );
|
||||
local( $i, $fp, $local );
|
||||
|
||||
#
|
||||
#quick check if it is already in there.
|
||||
#
|
||||
if( $mod_map{$dirname} ){
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@path = split(/\//, $dirname);
|
||||
|
||||
$fp = '';
|
||||
|
||||
for( $i = 0; $i < @path; $i++){
|
||||
|
||||
$fp .= ($fp ne '' ? '/' : '') . $path[$i];
|
||||
|
||||
if( $local = $mod_map->{$fp} ){
|
||||
if( $local == $IS_LOCAL ){
|
||||
if( $i == (@path-1) ){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
# Add directories to the map as we encounter them so we go
|
||||
# faster
|
||||
if( $mod_map{$dirname} == 0 ){
|
||||
$mod_map{$dirname} = $IS_LOCAL;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( $mod_map->{ $fp . '/' . $filename} ) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub get_module_map {
|
||||
local($name) = @_;
|
||||
local($mod_map);
|
||||
$mod_map = {};
|
||||
&build_map( $name, $mod_map );
|
||||
return $mod_map;
|
||||
}
|
||||
|
||||
sub parse_modules {
|
||||
while( $l = &get_line ){
|
||||
($mod_name, $flag, @params) = split(/[ \t]+/,$l);
|
||||
if( $flag ne '-a' ){
|
||||
next;
|
||||
}
|
||||
$modules->{$mod_name} = [@params];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub build_map {
|
||||
local($name,$mod_map) = @_;
|
||||
local($bFound, $local);
|
||||
|
||||
$local = $NOT_LOCAL;
|
||||
$bFound = 0;
|
||||
|
||||
for $i ( @{$modules->{$name}} ){
|
||||
$bFound = 1;
|
||||
if( $i eq '-l' ){
|
||||
$local = $IS_LOCAL;
|
||||
}
|
||||
elsif( !build_map($i, $mod_map )){
|
||||
$mod_map->{$i} = $local;
|
||||
}
|
||||
}
|
||||
return $bFound;
|
||||
}
|
||||
|
||||
|
||||
|
||||
sub get_line {
|
||||
local($l, $save);
|
||||
|
||||
$bContinue = 1;
|
||||
|
||||
while( $bContinue && ($l = <MOD>) ){
|
||||
chop($l);
|
||||
if( $l =~ /^[ \t]*\#/
|
||||
|| $l =~ /^[ \t]*$/ ){
|
||||
$l='';
|
||||
}
|
||||
elsif( $l =~ /\\[ \t]*$/ ){
|
||||
chop ($l);
|
||||
$save .= $l . ' ';
|
||||
}
|
||||
elsif( $l eq '' && $save eq ''){
|
||||
# ignore blank lines
|
||||
}
|
||||
else {
|
||||
$bContinue = 0;
|
||||
}
|
||||
}
|
||||
return $save . $l;
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
|
||||
#
|
||||
# Multi file diff cgi
|
||||
#
|
||||
|
||||
require 'utils.pl';
|
||||
|
||||
$|=1;
|
||||
|
||||
print "Content-type: text/html
|
||||
|
||||
<PRE><FONT FACE='Lucida Console'>
|
||||
";
|
||||
|
||||
@revs = ();
|
||||
|
||||
#if( $ENV{"QUERY_STRING"} eq "" ){
|
||||
# $ENV{"QUERY_STRING"}="brendan%2Cns%2Fjs%2Fsrc%2Cjsapi.c%2C-1=on&brendan%2Cns%2Fjs%2Fsrc%2Cjsapi.h%2C-1=on&brendan%2Cns%2Fjs%2Fsrc%2Cjsarray.c%2C-106=on&brendan%2Cns%2Fjs%2Fsrc%2Cjsarray.h%2C-0=on&brendan%2Cns%2Fjs%2Fsrc%2Cjsatom.c%2C-9=on";
|
||||
#}
|
||||
|
||||
&split_cgi_args;
|
||||
|
||||
#while( ($k,$v) = each(%ENV) ){
|
||||
# print "$k='$v'\n";
|
||||
#}
|
||||
|
||||
if( $form{"cvsroot"} ne "" ){
|
||||
$cvsroot = $form{"cvsroot"};
|
||||
}
|
||||
else {
|
||||
$cvsroot = pickDefaultRepository();
|
||||
}
|
||||
|
||||
if( $form{"allchanges"} ne "" ){
|
||||
@revs = split(/,/, $form{"allchanges"} );
|
||||
}
|
||||
else {
|
||||
while( ($k, $v) = each( %form ) ){
|
||||
push( @revs, $k );
|
||||
}
|
||||
}
|
||||
|
||||
$didone = 0;
|
||||
for $k (@revs) {
|
||||
($who,$dir,$file,$rev) = split(/\|/, $k );
|
||||
if ($rev eq "") {
|
||||
next;
|
||||
}
|
||||
$prevrev = &PrevRev($rev);
|
||||
|
||||
# this doesn't handle files in the attic
|
||||
open( DIFF, "/tools/ns/bin/rcsdiff -c -r$prevrev -r$rev $cvsroot/$dir/$file,v 2>&1|" );
|
||||
$_ =~ s/&/&/g;
|
||||
$_ =~ s/</</g;
|
||||
while(<DIFF>){
|
||||
print "$who: $_";
|
||||
}
|
||||
$didone = 1;
|
||||
}
|
||||
|
||||
if ($didone == 0) {
|
||||
print "No changes were selected. Please press <b>Back</b> and try again.\n";
|
||||
}
|
||||
|
||||
|
||||
|
||||
sub split_cgi_args {
|
||||
local($i,$var,$value, $s);
|
||||
|
||||
if( $ENV{"REQUEST_METHOD"} eq 'POST'){
|
||||
while(<> ){
|
||||
$s .= $_;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$s = $ENV{"QUERY_STRING"};
|
||||
}
|
||||
|
||||
@args= split(/\&/, $s );
|
||||
|
||||
for $i (@args) {
|
||||
($var, $value) = split(/=/, $i);
|
||||
$var =~ tr/+/ /;
|
||||
$var =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
|
||||
$value =~ tr/+/ /;
|
||||
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
|
||||
$form{$var} = $value;
|
||||
}
|
||||
}
|
||||
|
||||
sub PrevRev {
|
||||
local( $rev ) = @_;
|
||||
local( $i, $j, $ret, @r );
|
||||
|
||||
@r = split( /\./, $rev );
|
||||
|
||||
$i = @r-1;
|
||||
|
||||
$r[$i]--;
|
||||
if( $r[$i] == 0 ){
|
||||
$i -= 2;
|
||||
}
|
||||
|
||||
$j = 0;
|
||||
while( $j < $i ){
|
||||
$ret .= "$r[$j]\.";
|
||||
$j++
|
||||
}
|
||||
$ret .= $r[$i];
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
# -*- Mode: tcl; indent-tabs-mode: nil -*-
|
||||
|
||||
# The below was taken from the tclX distribution (version 7.4a), and modified
|
||||
# to quietly continue if it runs into a directory it doesn't have permission
|
||||
# to enter, and also to skip . directories.
|
||||
|
||||
|
||||
|
||||
#
|
||||
# globrecur.tcl --
|
||||
#
|
||||
# Build or process a directory list recursively.
|
||||
#------------------------------------------------------------------------------
|
||||
# Copyright 1992-1994 Karl Lehenbauer and Mark Diekhans.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose and without fee is hereby granted, provided
|
||||
# that the above copyright notice appear in all copies. Karl Lehenbauer and
|
||||
# Mark Diekhans make no representations about the suitability of this
|
||||
# software for any purpose. It is provided "as is" without express or
|
||||
# implied warranty.
|
||||
#------------------------------------------------------------------------------
|
||||
# $Id: myglobrecur.tcl,v 1.1 1998-06-16 21:43:04 terry Exp $
|
||||
#------------------------------------------------------------------------------
|
||||
#
|
||||
|
||||
|
||||
|
||||
proc my_for_recursive_glob {var dirlist globlist cmd {depth 1}} {
|
||||
upvar $depth $var myVar
|
||||
set recurse {}
|
||||
foreach dir $dirlist {
|
||||
if ![file isdirectory $dir] {
|
||||
error "\"$dir\" is not a directory"
|
||||
}
|
||||
set code 0
|
||||
set result {}
|
||||
foreach pattern $globlist {
|
||||
if {[catch {set list [glob -nocomplain -- $dir/$pattern]}]} {
|
||||
continue
|
||||
}
|
||||
foreach file $list {
|
||||
set myVar $file
|
||||
set code [catch {uplevel $depth $cmd} result]
|
||||
if {$code != 0 && $code != 4} break
|
||||
}
|
||||
if {$code != 0 && $code != 4} break
|
||||
}
|
||||
if {$code != 0 && $code != 4} {
|
||||
if {$code == 3} {
|
||||
return $result
|
||||
}
|
||||
if {$code == 1} {
|
||||
global errorCode errorInfo
|
||||
return -code $code -errorcode $errorCode \
|
||||
-errorinfo $errorInfo $result
|
||||
}
|
||||
return -code $code $result
|
||||
}
|
||||
|
||||
if {[catch {set list [readdir $dir]}]} {
|
||||
continue
|
||||
}
|
||||
foreach file $list {
|
||||
set file $dir/$file
|
||||
if [file isdirectory $file] {
|
||||
set fileTail [file tail $file]
|
||||
if {![cequal "." [crange $fileTail 0 0]]} {
|
||||
lappend recurse $file
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ![lempty $recurse] {
|
||||
return [my_for_recursive_glob $var $recurse $globlist $cmd \
|
||||
[expr {$depth + 1}]]
|
||||
}
|
||||
return {}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
From: bonsai-daemon
|
||||
To: %name%
|
||||
Subject: [Bonsai] You're on the hook now!
|
||||
Mime-Version: 1.0
|
||||
Content-Type: text/html
|
||||
|
||||
<HTML>
|
||||
|
||||
<H1>You are responsible to make sure the build works.</H1>
|
||||
|
||||
You just checked into <tt>%dir%</tt> the files <tt>%files%</tt>. At
|
||||
about <tt>%nextclose%</tt>, the tree will be frozen. From about
|
||||
an hour later on, you are to be available for the build team to pester
|
||||
in case of any problems.
|
||||
|
||||
<P>
|
||||
|
||||
Any further checkins you make before the tree closes will <i>not</i>
|
||||
cause you to receive more copies of this mail, but you'll be held
|
||||
responsible for them too.
|
||||
|
||||
<P>
|
||||
|
||||
For more info on the current state of the tree, see the
|
||||
<a href=http://warp/bonsai/toplevel.cgi>Bonsai main page</a>.
|
||||
|
||||
<P>
|
||||
|
||||
Your contact info and other vital data is listed below. Please
|
||||
<a href=http://warp/bonsai/profile.cgi?person=%name%>update</a>
|
||||
this info <b>immediately</b> if it is at all inaccurate or incorrect.
|
||||
|
||||
<hr>
|
||||
|
||||
%profile%
|
|
@ -0,0 +1,83 @@
|
|||
#!/usr/bonsaitools/bin/mysqltcl
|
||||
# -*- Mode: tcl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
# Oy, what a hack.
|
||||
#
|
||||
# Bonsai has a split heritage, and so some of it is written in Perl, and
|
||||
# some of it is written in TCL. The perl half wants to be able to look
|
||||
# at the basic configuration, kept in data/configdata. But that file is
|
||||
# designed to be quickly read by TCL. And I don't feel like writing perl
|
||||
# code to parse it. So, instead, we have this hack which will read the
|
||||
# file and push it out in a form friendlier to perl. Gross, gross, gross.
|
||||
|
||||
|
||||
source globals.tcl
|
||||
|
||||
proc haschar {str char} {
|
||||
return [string match "*$char*" $str]
|
||||
}
|
||||
|
||||
proc PerlStringify {str} {
|
||||
if {![haschar $str "'"]} {
|
||||
return "'$str'"
|
||||
}
|
||||
foreach i [list "/" ":" "@" "#" "%" "^"] {
|
||||
if {![haschar $str $i]} {
|
||||
return "q$i$str$i"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Lock
|
||||
LoadTreeConfig
|
||||
|
||||
set outfilename "data/configdata.pl"
|
||||
set fid [open $outfilename "w"]
|
||||
puts $fid "\# WARNING! Do not edit this file! Automatically generated!"
|
||||
puts $fid "\# You want to instead edit the 'configdata' file. This file"
|
||||
puts $fid "\# gets automatically generated from that one."
|
||||
puts $fid ""
|
||||
regsub -all {(^|[^\])&} $BUGSYSTEMEXPR {\1$\&} BUGSYSTEMEXPR
|
||||
puts $fid "\$BUGSYSTEMEXPR = [PerlStringify $BUGSYSTEMEXPR];"
|
||||
set list ""
|
||||
foreach i $treelist {
|
||||
append list [PerlStringify $i]
|
||||
append list ", "
|
||||
}
|
||||
puts $fid "@treelist = ($list);"
|
||||
|
||||
foreach i [lsort [array names treeinfo]] {
|
||||
lassign [split $i ","] a b
|
||||
if {![info exists done($a)]} {
|
||||
set done($a) 1
|
||||
puts $fid "\$treeinfo{[PerlStringify $a]} = {};"
|
||||
}
|
||||
puts $fid "\$treeinfo{[PerlStringify $a]}->{[PerlStringify $b]} = [PerlStringify $treeinfo($i)];"
|
||||
}
|
||||
|
||||
|
||||
close $fid
|
||||
catch {chmod 0666 $outfilename}
|
||||
|
||||
Unlock
|
|
@ -0,0 +1,35 @@
|
|||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
# This takes a bunch of files that have been put into the 'bonsai
|
||||
# queue' (the 'queue' subdirectory) and processes them as checkins.
|
||||
# This is to work around worlds where we can't send mail from inside
|
||||
# the CVS loginfo file.
|
||||
#
|
||||
# Each file is expected to have the CVSROOT in the first line, any args in the
|
||||
# second line (currently unused), and the data fed to loginfo as the remaining
|
||||
# lines.
|
||||
|
||||
$inprocess = "data/queue/processing-$$";
|
||||
|
||||
foreach $file (sort(glob("data/queue/*.q"))) {
|
||||
rename $file, $inprocess || die "Couldn't rename queue file.";
|
||||
system "./dolog.pl < $inprocess";
|
||||
rename $inprocess, "$file.done";
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
#!/usr/bonsaitools/bin/mysqltcl
|
||||
# -*- Mode: tcl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
source CGI.tcl
|
||||
|
||||
|
||||
|
||||
|
||||
if {![info exists FORM(person)]} {
|
||||
puts {
|
||||
<TITLE>Uh, who?</TITLE>
|
||||
<H1>Who would you like to know more about?</H1>
|
||||
Please enter the username of the person whose Bonsai profile
|
||||
you'd like to see.
|
||||
<p>
|
||||
<form method=get action="profile.cgi">
|
||||
<B>User:</B><INPUT SIZE=10 NAME=person>
|
||||
<INPUT TYPE=SUBMIT Value="Submit"></FORM>
|
||||
}
|
||||
PutsTrailer
|
||||
exit
|
||||
}
|
||||
|
||||
|
||||
set fid [open "|./data/ldapsearch -b \"o=Netscape Communications Corp.,c=US\" -h $ldapserver -p $ldapport -s sub \"(mail=$FORM(person)@netscape.com)\" cn" r]
|
||||
|
||||
while {[gets $fid line] >= 0} {
|
||||
if {[regexp -- {^cn: (.*)$} $line foo n]} {
|
||||
set fullname $n
|
||||
}
|
||||
}
|
||||
|
||||
close $fid
|
||||
|
||||
if {![info exists fullname]} {
|
||||
puts {
|
||||
<TITLE>Uh, who?</TITLE>
|
||||
<H1>Who would you like to know more about?</H1>
|
||||
There doesn't seem to be anybody with e-mail address
|
||||
<b><tt>$FORM(person)</tt></b>.
|
||||
|
||||
<p>
|
||||
|
||||
Please enter the username of the person whose Bonsai profile
|
||||
you'd like to see.
|
||||
<p>
|
||||
<form method=get action="profile.cgi">
|
||||
<B>User:</B><INPUT SIZE=10 NAME=person>
|
||||
<INPUT TYPE=SUBMIT Value="Submit"></FORM>
|
||||
}
|
||||
PutsTrailer
|
||||
exit
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
puts "Content-type: text/html
|
||||
Refresh: 0; URL=http://phonebook/cgi-bin/expand-entry.pl?fullname=[url_quote "$fullname,o=Netscape Communications Corp.,c=US"]
|
||||
|
||||
<HTML>
|
||||
<TITLE>What a hack.</TITLE>
|
||||
One moment while we whisk you away to the appropriate phonebook page..."
|
||||
|
||||
|
||||
|
||||
exit
|
|
@ -0,0 +1,386 @@
|
|||
#!/usr/bonsaitools/bin/mysqltcl
|
||||
# -*- Mode: tcl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
source CGI.tcl
|
||||
source myglobrecur.tcl
|
||||
|
||||
if {[llength $argv] == 5} {
|
||||
lassign $argv treeid FORM(startfrom) FORM(firstfile) FORM(subdir) FORM(modules)
|
||||
} else {
|
||||
puts "Content-type: text/plain
|
||||
|
||||
<HTML>"
|
||||
|
||||
CheckPassword $FORM(password)
|
||||
}
|
||||
|
||||
set startfrom [ParseTimeAndCheck [FormData startfrom]]
|
||||
|
||||
set firstfile [string trim [FormData firstfile]]
|
||||
|
||||
set subdir [string trim [FormData subdir]]
|
||||
|
||||
Lock
|
||||
LoadTreeConfig
|
||||
Unlock
|
||||
|
||||
ConnectToDatabase
|
||||
|
||||
set repository $treeinfo($treeid,repository)
|
||||
regsub -all -- / $repository _ mungedname
|
||||
|
||||
puts "Rebuilding entire checkin history in $treeinfo($treeid,description) ..."
|
||||
flush stdout
|
||||
|
||||
|
||||
|
||||
# cmdtrace on
|
||||
|
||||
set repositoryid [GetId repositories repository $repository]
|
||||
|
||||
proc ProcessOneFile {filename} {
|
||||
global repository startfrom
|
||||
|
||||
puts "$filename"
|
||||
flush stdout
|
||||
set fid [open "|/tools/ns/bin/rlog $filename" r]
|
||||
set doingtags 0
|
||||
catch {unset branchname}
|
||||
regsub -- {,v$} $filename {} filerealname
|
||||
set filehead [file dirname $filerealname]
|
||||
regsub -- "^$repository" $filehead {} filehead
|
||||
regsub -- {^/} $filehead {} filehead
|
||||
if {[clength $filehead] == 0} {
|
||||
set filehead "."
|
||||
}
|
||||
set filetail [file tail $filerealname]
|
||||
while {1} {
|
||||
if {[gets $fid line] < 0} {
|
||||
break
|
||||
}
|
||||
set trimmed [string trim $line]
|
||||
if {$doingtags} {
|
||||
if {![cequal "\t" [crange $line 0 0]]} {
|
||||
set doingtags 0
|
||||
} else {
|
||||
lassign [split $trimmed ":"] tag version
|
||||
if {[clength $tag] == 0 || [clength $version] == 0} {
|
||||
continue
|
||||
}
|
||||
set version [string trim $version]
|
||||
|
||||
set branchid [GetId branches branch $tag]
|
||||
set dirid [GetId dirs dir $filehead]
|
||||
set fileid [GetId files file $filetail]
|
||||
# Don't touch the tags database for now. Nothing uses it, and it just takes
|
||||
# up too much damn space.
|
||||
# SendSQL "replace into tags (branchid, repositoryid, dirid, fileid, revision) values ($branchid, $repositoryid, $dirid, $fileid, '$version')"
|
||||
|
||||
set vlist [split $version '.']
|
||||
set sub [expr [llength $vlist] - 2]
|
||||
if {[cequal "0" [lindex $vlist $sub]]} {
|
||||
# Aha! Second-to-last being a zero is CVS's special way
|
||||
# of remembering a branch tag.
|
||||
set bnum [join [lreplace $vlist $sub $sub] "."]
|
||||
set branchname($bnum) $tag
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
switch -regexp -- $line {
|
||||
{^symbolic names} {
|
||||
set doingtags 1
|
||||
}
|
||||
{^revision ([0-9.]*)$} {
|
||||
set indesc 0
|
||||
while {1} {
|
||||
if {$indesc} {
|
||||
if {[cequal $line "----------------------------"] ||
|
||||
[cequal $line "============================================================================="]} {
|
||||
# OK, we're done. Write it out.
|
||||
if {[info exists revision] &&
|
||||
[info exists datestr] &&
|
||||
[info exists author]} {
|
||||
if {[regexp -- {^([0-9]*)/([0-9]*)/([0-9]*) ([0-9]*):([0-9]*):([0-9]*)$} $datestr foo year month day hours mins secs]} {
|
||||
set date [convertclock "$month/$day/$year $hours:$mins:$secs" GMT]
|
||||
|
||||
if {$date >= $startfrom} {
|
||||
set tbranch "T$branch"
|
||||
if {[cequal $tbranch "T"]} {
|
||||
set tbranch ""
|
||||
}
|
||||
set entrystr "C|$date|$author|$repository|$filehead|$filetail|$revision||$branch|+$pluscount|-$minuscount"
|
||||
AddToDatabase $entrystr $desc
|
||||
}
|
||||
}
|
||||
}
|
||||
set indesc 0
|
||||
} else {
|
||||
append desc $line
|
||||
append desc "\n"
|
||||
}
|
||||
} else {
|
||||
switch -regexp -- $line {
|
||||
{^revision ([0-9.]*)$} {
|
||||
if {[regexp -- {^revision ([0-9.]*)$} $line foo new]} {
|
||||
set revision $new
|
||||
catch {unset datestr}
|
||||
catch {unset author}
|
||||
set pluscount 0
|
||||
set minuscount 0
|
||||
set desc {}
|
||||
|
||||
regsub -- {.[0-9]*$} $revision {} bnum
|
||||
if {[info exists branchname($bnum)]} {
|
||||
set branch "$branchname($bnum)"
|
||||
} else {
|
||||
set branch ""
|
||||
}
|
||||
}
|
||||
}
|
||||
{^date:} {
|
||||
regexp -- {^date: ([0-9 /:]*); author: ([^;]*);} $line foo datestr author
|
||||
regexp -- {lines: \+([0-9]*) -([0-9]*)} $line foo pluscount minuscount
|
||||
}
|
||||
{^branches: [0-9 .;]*$} {
|
||||
# Ignore these lines; make sure they don't
|
||||
# become part of the desciption.
|
||||
}
|
||||
default {
|
||||
set indesc 1
|
||||
set desc "$line\n"
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
if {[gets $fid line] < 0} {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {close $fid}
|
||||
}
|
||||
|
||||
|
||||
proc ProcessDirectory {dir} {
|
||||
global firstfile
|
||||
my_for_recursive_glob filename $dir "*,v" {
|
||||
if {![cequal $firstfile ""]} {
|
||||
if {![cequal $filename $firstfile]} {
|
||||
puts "Skipping $filename"
|
||||
flush stdout
|
||||
continue
|
||||
}
|
||||
set firstfile ""
|
||||
}
|
||||
ProcessOneFile $filename
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
proc digest {str} {
|
||||
global array
|
||||
set key [lvarpop str]
|
||||
if {[cequal [cindex [lindex $str 0] 0] "-"]} {
|
||||
lvarpop str
|
||||
}
|
||||
set array($key) $str
|
||||
}
|
||||
|
||||
|
||||
|
||||
set env(CVSROOT) $treeinfo($treeid,repository)
|
||||
set origdir [pwd]
|
||||
cd /
|
||||
set fid [open "|/tools/ns/bin/cvs checkout -c" r]
|
||||
cd $origdir
|
||||
|
||||
set curline ""
|
||||
while {[gets $fid line] >= 0} {
|
||||
if {[ctype space [cindex $line 0]]} {
|
||||
append curline $line
|
||||
} else {
|
||||
digest $curline
|
||||
set curline $line
|
||||
}
|
||||
}
|
||||
digest $curline
|
||||
close $fid
|
||||
|
||||
|
||||
set startingdir $repository/$subdir
|
||||
|
||||
regsub -- {/\.$} $startingdir {} startingdir
|
||||
regsub -- {/$} $startingdir {} startingdir
|
||||
|
||||
|
||||
set oldlist {}
|
||||
|
||||
set list {}
|
||||
|
||||
if {[info exists FORM(modules)]} {
|
||||
set list [split $FORM(modules) ","]
|
||||
}
|
||||
|
||||
if {[lempty $list]} {
|
||||
set list $treeinfo($treeid,module)
|
||||
}
|
||||
|
||||
|
||||
while {![cequal $list $oldlist]} {
|
||||
set oldlist $list
|
||||
set list {}
|
||||
foreach i $oldlist {
|
||||
if {[info exists array($i)]} {
|
||||
set list [concat $list $array($i)]
|
||||
# Do an unset to prevent infinite recursion.
|
||||
unset array($i)
|
||||
} else {
|
||||
lappend list $i
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
set tlist {}
|
||||
catch {unset present}
|
||||
foreach i $list {
|
||||
if {![info exists present($i)]} {
|
||||
lappend tlist $i
|
||||
set present($i) 1
|
||||
}
|
||||
}
|
||||
catch {unset present}
|
||||
|
||||
|
||||
set list {}
|
||||
|
||||
foreach i $tlist {
|
||||
set d $repository/$i
|
||||
regsub -- {/\.$} $d {} d
|
||||
regsub -- {/$} $d {} d
|
||||
lappend list $d
|
||||
}
|
||||
|
||||
if {[lempty $list]} {
|
||||
set $list $startingdir
|
||||
}
|
||||
|
||||
set slen [expr [clength $startingdir] - 1]
|
||||
|
||||
puts "Doing directories: $list"
|
||||
|
||||
foreach dir $list {
|
||||
if {![cequal [crange $dir 0 $slen] $startingdir]} {
|
||||
puts "*** Skipping $dir ***"
|
||||
continue
|
||||
}
|
||||
if {![file isdirectory $dir]} {
|
||||
if {[file isfile $dir]} {
|
||||
ProcessOneFile $dir
|
||||
}
|
||||
} else {
|
||||
ProcessDirectory $dir
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
# puts "<HR>Putting entries ($count unique descriptions) into database...<P>"
|
||||
# flush stdout
|
||||
|
||||
# set infid [open data/checkinlog$mungedname "r"]
|
||||
|
||||
# ConnectToDatabase
|
||||
|
||||
# set buffer {}
|
||||
# set desc {}
|
||||
# set indesc 0
|
||||
# set done 0
|
||||
# while {[gets $infid line] >= 0} {
|
||||
# if {$indesc} {
|
||||
# if {[cequal $line ":ENDLOGCOMMENT"]} {
|
||||
# AddToDatabase $buffer $desc
|
||||
# set buffer {}
|
||||
# set desc {}
|
||||
# set indesc 0
|
||||
# incr done
|
||||
# if {$done % 5 == 0} {
|
||||
# puts "$done done.<BR>"
|
||||
# flush stdout
|
||||
# }
|
||||
# } else {
|
||||
# append desc $line
|
||||
# append desc "\n"
|
||||
# }
|
||||
# } else {
|
||||
# if {[cequal $line "LOGCOMMENT"]} {
|
||||
# set indesc 1
|
||||
# } else {
|
||||
# append buffer $line
|
||||
# append buffer "\n"
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# close $infid
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# puts "<HR>"
|
||||
# flush stdout
|
||||
|
||||
# set dir data/taginfo
|
||||
# catch {mkdir $dir}
|
||||
# catch {chmod 0777 $dir}
|
||||
# append dir /tmp_[set mungedname]_[id process]
|
||||
# catch {mkdir $dir}
|
||||
# catch {chmod 0777 $dir}
|
||||
|
||||
# set numtags 0
|
||||
|
||||
# foreach n [lsort [info var tag_*]] {
|
||||
# upvar #0 $n t
|
||||
# set tagname [crange $n 4 end]
|
||||
# puts "Dumping tag $tagname<br>"
|
||||
# flush stdout
|
||||
# set filename $dir/[MungeTagName $tagname]
|
||||
# set fid [open "$filename" "w"]
|
||||
# foreach f [lsort [array names t]] {
|
||||
# puts $fid "0|add|$f|$t($f)"
|
||||
# }
|
||||
# close $fid
|
||||
# incr numtags
|
||||
# }
|
||||
|
||||
|
||||
# Lock
|
||||
# set newdir data/taginfo/$mungedname
|
||||
# catch {exec rm -rf $newdir}
|
||||
# frename $dir $newdir
|
||||
# Unlock
|
||||
|
||||
# puts "<HR><P>Done. $numfiles files checked; $numtags tags created.<P>"
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
#!/usr/bonsaitools/bin/mysqltcl
|
||||
# -*- Mode: tcl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
source CGI.tcl
|
||||
source myglobrecur.tcl
|
||||
|
||||
puts "Content-type: text/html
|
||||
|
||||
<HTML>"
|
||||
|
||||
CheckPassword $FORM(password)
|
||||
|
||||
Lock
|
||||
LoadTreeConfig
|
||||
Unlock
|
||||
|
||||
set repository $treeinfo($treeid,repository)
|
||||
regsub -all -- / $repository _ mungedname
|
||||
|
||||
puts "<H1>Searching for tags in all files in $repository ...</h1>"
|
||||
flush stdout
|
||||
|
||||
set numfiles 0
|
||||
set numtags 0
|
||||
|
||||
my_for_recursive_glob filename $repository "*,v" {
|
||||
puts "$filename<br>"
|
||||
flush stdout
|
||||
set fid [open "|/tools/ns/bin/rlog -h $filename" r]
|
||||
set doingtags 0
|
||||
while {1} {
|
||||
if {[gets $fid line] < 0} {
|
||||
break
|
||||
}
|
||||
if {$doingtags} {
|
||||
if {![cequal "\t" [crange $line 0 0]]} {
|
||||
break
|
||||
}
|
||||
lassign [split [string trim $line] ":"] tag version
|
||||
if {[clength $tag] == 0 || [clength $version] == 0} {
|
||||
continue
|
||||
}
|
||||
set tag_[set tag]($cutename) [string trim $version]
|
||||
} elseif {[cequal [string trim $line] "symbolic names:"]} {
|
||||
set doingtags 1
|
||||
regsub -- {,v$} $filename {} tmp
|
||||
regsub -- {/([^/]*$)} $tmp {|\1} cutename
|
||||
}
|
||||
}
|
||||
catch {close $fid}
|
||||
incr numfiles
|
||||
}
|
||||
|
||||
puts "<HR>"
|
||||
flush stdout
|
||||
|
||||
set dir data/taginfo
|
||||
catch {mkdir $dir}
|
||||
catch {chmod 0777 $dir}
|
||||
append dir /tmp_[set mungedname]_[id process]
|
||||
catch {mkdir $dir}
|
||||
catch {chmod 0777 $dir}
|
||||
|
||||
foreach n [lsort [info var tag_*]] {
|
||||
upvar #0 $n t
|
||||
set tagname [crange $n 4 end]
|
||||
puts "Dumping tag $tagname<br>"
|
||||
flush stdout
|
||||
set filename $dir/[MungeTagName $tagname]
|
||||
set fid [open "$filename" "w"]
|
||||
foreach f [lsort [array names t]] {
|
||||
puts $fid "0|add|$f|$t($f)"
|
||||
}
|
||||
close $fid
|
||||
incr numtags
|
||||
}
|
||||
|
||||
|
||||
Lock
|
||||
set newdir data/taginfo/$mungedname
|
||||
catch {exec rm -rf $newdir}
|
||||
frename $dir $newdir
|
||||
Unlock
|
||||
|
||||
puts "<HR><P>Done. $numfiles files checked; $numtags tags created.<P>"
|
||||
|
||||
PutsTrailer
|
|
@ -0,0 +1,134 @@
|
|||
#!/usr/bonsaitools/bin/mysqltcl
|
||||
# -*- Mode: tcl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
source CGI.tcl
|
||||
|
||||
puts "Content-type: text/html
|
||||
|
||||
<HTML>"
|
||||
|
||||
CheckPassword $FORM(password)
|
||||
|
||||
set startfrom [ParseTimeAndCheck [FormData startfrom]]
|
||||
|
||||
Lock
|
||||
LoadTreeConfig
|
||||
LoadCheckins
|
||||
set checkinlist {}
|
||||
WriteCheckins
|
||||
Unlock
|
||||
|
||||
|
||||
puts "<TITLE> Rebooting, please wait...</TITLE>
|
||||
|
||||
<H1>Recreating the hook</H1>
|
||||
|
||||
<h3>$treeinfo($treeid,description)</h3>
|
||||
|
||||
<p>
|
||||
Searching for first checkin after [MyFmtClock $startfrom]...<p>"
|
||||
|
||||
flush stdout
|
||||
|
||||
regsub -all -- / $treeinfo($treeid,repository) _ mungedname
|
||||
set filename "data/checkinlog$mungedname"
|
||||
|
||||
set fid [open $filename "r"]
|
||||
|
||||
|
||||
set foundfirst 0
|
||||
|
||||
set buffer {}
|
||||
|
||||
|
||||
set tempfile data/repophook.[id process]
|
||||
|
||||
proc FlushBuffer {} {
|
||||
global buffer tempfile treeid foundfirst count
|
||||
if {!$foundfirst || [cequal $buffer ""]} {
|
||||
return
|
||||
}
|
||||
write_file $tempfile "junkline\n\n$buffer"
|
||||
exec ./addcheckin.tcl -treeid $treeid $tempfile
|
||||
unlink $tempfile
|
||||
set buffer {}
|
||||
incr count
|
||||
if {$count % 100 == 0} {
|
||||
puts "$count scrutinized...<br>"
|
||||
flush stdout
|
||||
}
|
||||
}
|
||||
|
||||
set now [getclock]
|
||||
set count 0
|
||||
set lastdate 0
|
||||
|
||||
while {[gets $fid line] >= 0} {
|
||||
switch -glob -- $line {
|
||||
{?|*} {
|
||||
lassign [split $line "|"] chtype date
|
||||
if {$date < $lastdate} {
|
||||
puts "Ick; dates out of order!<br>"
|
||||
puts "<pre>[value_quote $line]</pre><p>"
|
||||
}
|
||||
set $lastdate $date
|
||||
if {$foundfirst} {
|
||||
append buffer "$line\n"
|
||||
} else {
|
||||
if {$date >= $startfrom} {
|
||||
if {$date >= $now} {
|
||||
puts "Found a future date! (ignoring):<br>"
|
||||
puts "<pre>[value_quote $line]</pre><p>"
|
||||
flush stdout
|
||||
} else {
|
||||
set foundfirst 1
|
||||
puts "Found first line: <br><pre>[value_quote $line]</pre><p>"
|
||||
puts "OK, now processing checkins...<p>"
|
||||
flush stdout
|
||||
set buffer "$line\n"
|
||||
set count 0
|
||||
}
|
||||
} else {
|
||||
incr count
|
||||
if {$count % 2000 == 0} {
|
||||
puts "Skipped $count lines...<p>"
|
||||
flush stdout
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
{:ENDLOGCOMMENT} {
|
||||
append buffer "$line\n"
|
||||
FlushBuffer
|
||||
}
|
||||
default {
|
||||
append buffer "$line\n"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FlushBuffer
|
||||
|
||||
|
||||
catch {unset checkinlist}
|
||||
LoadCheckins
|
||||
|
||||
puts "Done. [llength $checkinlist] relevant checkins were found."
|
||||
|
||||
PutsTrailer
|
|
@ -0,0 +1,58 @@
|
|||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
|
||||
if( $ARGV[0] eq '' ){
|
||||
$CVS_ROOT = '/m/src';
|
||||
}
|
||||
else {
|
||||
$CVS_ROOT = $ARGV[0];
|
||||
}
|
||||
|
||||
$CVS_REPOS_SUFIX = $CVS_ROOT;
|
||||
$CVS_REPOS_SUFIX =~ s/\//_/g;
|
||||
|
||||
|
||||
$FILE_LIST = "/d/webdocs/projects/bonsai/data/reposfiles${CVS_REPOS_SUFIX}";
|
||||
|
||||
open FL, ">$FILE_LIST";
|
||||
|
||||
GoDir($CVS_ROOT);
|
||||
|
||||
sub GoDir {
|
||||
local($dir) = @_;
|
||||
local(@dirs, $i);
|
||||
|
||||
chdir "$dir";
|
||||
|
||||
while(<*> ){
|
||||
if( $_ ne '.' && $_ ne '..' ){
|
||||
if( -d $_ ) {
|
||||
push @dirs, $_;
|
||||
}
|
||||
else {
|
||||
print FL "$dir/$_\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for $i (@dirs) {
|
||||
GoDir( "$dir/$i");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,196 @@
|
|||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
|
||||
#
|
||||
# Query the CVS database.
|
||||
#
|
||||
require 'lloydcgi.pl';
|
||||
require 'cvsmenu.pl';
|
||||
|
||||
$|=1;
|
||||
|
||||
$CVS_ROOT = $form{"cvsroot"};
|
||||
|
||||
# get dir, remove leading and trailing slashes
|
||||
|
||||
$dir = $form{"dir"};
|
||||
$dir =~ s/^\/([^:]*)/$1/;
|
||||
$dir =~ s/([^:]*)\/$/$1/;
|
||||
|
||||
$rev = $form{"rev"};
|
||||
|
||||
print "Content-type: text/html
|
||||
|
||||
<HTML>";
|
||||
|
||||
|
||||
&setup_script;
|
||||
print $script_str;
|
||||
|
||||
|
||||
if( $CVS_ROOT eq "" ){
|
||||
$CVS_ROOT = pickDefaultRepository();
|
||||
}
|
||||
|
||||
validateRepository($CVS_ROOT);
|
||||
|
||||
if( $rev ne "" ){
|
||||
$s = "for branch <i>$rev</i>";
|
||||
}
|
||||
|
||||
print "
|
||||
<head><title>Repository Directory $CVS_ROOT/$dir $s</title></head>";
|
||||
|
||||
$output = "<DIV ALIGN=LEFT>";
|
||||
|
||||
($dir_head, $dir_tail) = $dir =~ m@(.*/)?(.+)@;
|
||||
foreach $path (split('/',$dir_head)) {
|
||||
$link_path .= $path;
|
||||
$output .= "<A HREF='rview.cgi?dir=$link_path";
|
||||
$output .= "&cvsroot=$form{'cvsroot'}" if defined $form{'cvsroot'};
|
||||
$output .= "&rev=$rev" unless $rev eq '';
|
||||
$output .= "'>$path</A>/ ";
|
||||
$link_path .= '/';
|
||||
}
|
||||
chop ($output);
|
||||
$output .= " $s";
|
||||
$output .= "</DIV>";
|
||||
|
||||
EmitHtmlHeader("Repository Directory", $output);
|
||||
|
||||
cvsmenu("align=right width=20%");
|
||||
|
||||
chdir "$CVS_ROOT/$dir";
|
||||
|
||||
print "
|
||||
<TABLE CELLPADDING=0 CELLSPACING=0>
|
||||
<FORM action=rview.cgi method=get><TR><TD>
|
||||
Goto Directory:
|
||||
</TD><TD><INPUT name=dir value='$dir' size=30>
|
||||
<INPUT name=rev value='$rev' type=hidden>
|
||||
<INPUT name=cvsroot value='$CVS_ROOT' type=hidden>
|
||||
<INPUT type=submit value='chdir'>
|
||||
</TD></TR></FORM>
|
||||
<FORM action=rview.cgi method=get><TR><TD>
|
||||
Branch:
|
||||
</TD><TD><INPUT name=rev value='$rev' size=30>
|
||||
<INPUT name=dir value='$dir' type=hidden>
|
||||
<INPUT name=cvsroot value='$CVS_ROOT' type=hidden>
|
||||
<INPUT type=submit value='Set Branch'>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
";
|
||||
|
||||
@dirs = ();
|
||||
|
||||
while( <*> ){
|
||||
if( -d $_ ){
|
||||
push @dirs, $_;
|
||||
}
|
||||
}
|
||||
|
||||
if( @dirs != 0 ){
|
||||
$j = 1;
|
||||
$split = int(@dirs/4)+1;
|
||||
print "<P><FONT SIZE=+1><B>Directories:</B></FONT><table><TR VALIGN=TOP><td>";
|
||||
|
||||
|
||||
for $i (@dirs){
|
||||
$form{"dir"} = ($dir ne "" ? "$dir/$i" : $i);
|
||||
$anchor = &make_cgi_args;
|
||||
print "<dt><a href=rview.cgi${anchor}>$i</a>\n";
|
||||
if( $j % $split == 0 ){
|
||||
print "\n<td>\n";
|
||||
}
|
||||
$j++;
|
||||
}
|
||||
$form{"dir"} = $dir;
|
||||
print "\n</tr></table>\n";
|
||||
}
|
||||
|
||||
|
||||
print "<P><FONT SIZE=+1><B>Files:</B></FONT>";
|
||||
print "<table><TR VALIGN=TOP><td>";
|
||||
@files = <*,v>;
|
||||
$j = 1;
|
||||
$split = int(@files/4)+1;
|
||||
|
||||
for $_ (@files){
|
||||
$_ =~ s/\,v//;
|
||||
print "<a href=../registry/file.cgi?cvsroot=$CVS_ROOT&file=$_&dir=$dir"
|
||||
. " onclick=\"return js_file_menu('$dir','$_','$rev','$CVS_ROOT',event)\">\n";
|
||||
print "<dt>$_</a>\n";
|
||||
if( $j % $split == 0 ){
|
||||
print "\n<td>\n";
|
||||
}
|
||||
$j++;
|
||||
}
|
||||
print "\n</tr></table>\n";
|
||||
|
||||
|
||||
sub setup_script {
|
||||
|
||||
$script_str =<<'ENDJS';
|
||||
<script>
|
||||
|
||||
var event = new Object;
|
||||
|
||||
function js_who_menu(n,extra,d) {
|
||||
if( parseInt(navigator.appVersion) < 4 ){
|
||||
return true;
|
||||
}
|
||||
l = document.layers['popup'];
|
||||
l.src="../registry/who.cgi?email="+n+extra;
|
||||
l.top = d.target.y - 6;
|
||||
l.left = d.target.x - 6;
|
||||
if( l.left + l.clipWidth > window.width ){
|
||||
l.left = window.width - l.clipWidth;
|
||||
}
|
||||
l.visibility="show";
|
||||
return false;
|
||||
}
|
||||
|
||||
function js_file_menu(dir,file,rev,root,d) {
|
||||
if( parseInt(navigator.appVersion) < 4 ){
|
||||
return true;
|
||||
}
|
||||
l = document.layers['popup'];
|
||||
l.src="../registry/file.cgi?file="+file+"&dir="+dir+"&rev="+rev+"&cvsroot="+root+"&linked_text="+d.target.text;
|
||||
|
||||
l.top = d.target.y - 6;
|
||||
l.left = d.target.x - 6;
|
||||
if( l.left + l.clipWidth > window.width ){
|
||||
l.left = window.width - l.clipWidth;
|
||||
}
|
||||
l.visibility="show";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<layer name="popup" onMouseOut="this.visibility='hide';" left=0 top=0 bgcolor="#ffffff" visibility="hide">
|
||||
</layer>
|
||||
|
||||
ENDJS
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,350 @@
|
|||
#!/usr/bonsaitools/bin/mysqltcl
|
||||
# -*- Mode: tcl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
source CGI.tcl
|
||||
|
||||
Lock
|
||||
LoadCheckins
|
||||
LoadTreeConfig
|
||||
Unlock
|
||||
|
||||
|
||||
# Stupid hack to make an empty array:
|
||||
set peoplearray(zzz) 1
|
||||
unset peoplearray(zzz)
|
||||
set versioninfo ""
|
||||
|
||||
proc BreakBig {str} {
|
||||
set result {}
|
||||
while {[clength $str] > 20} {
|
||||
set head [crange $str 0 19]
|
||||
set w [string last "/" $head]
|
||||
if {$w < 0} {
|
||||
set w 19
|
||||
}
|
||||
append result "[crange $str 0 $w]<br>"
|
||||
incr w
|
||||
set str [crange $str $w end]
|
||||
}
|
||||
append result $str
|
||||
}
|
||||
|
||||
|
||||
|
||||
set tweak [info exists FORM(tweak)]
|
||||
|
||||
set delta_size 1 ;#[info exists FORM(delta_size)]
|
||||
|
||||
puts "Content-type: text/html"
|
||||
|
||||
if {[info exists FORM(sort)]} {
|
||||
puts "Set-Cookie: SORT=$FORM(sort)"
|
||||
} elseif {[info exists COOKIE(SORT)]} {
|
||||
set FORM(sort) $COOKIE(SORT)
|
||||
} else {
|
||||
set FORM(sort) date
|
||||
}
|
||||
|
||||
puts "
|
||||
<HTML>"
|
||||
|
||||
if {[info exists FORM(person)]} {
|
||||
puts "<TITLE>Checkins for $FORM(person)</TITLE>"
|
||||
puts "<H1>Checkins for $FORM(person)</H1>"
|
||||
set list {}
|
||||
foreach i $checkinlist {
|
||||
upvar #0 $i info
|
||||
if {[cequal $info(person) $FORM(person)]} {
|
||||
lappend list $i
|
||||
}
|
||||
}
|
||||
} elseif {[info exists FORM(mindate)] || [info exists FORM(maxdate)]} {
|
||||
set str "Checkins"
|
||||
set min 0
|
||||
set max [expr 1<<30]
|
||||
if {[info exists FORM(mindate)]} {
|
||||
set min $FORM(mindate)
|
||||
append str " since [fmtclock $min "%m/%d %H:%M"]"
|
||||
if {[info exists FORM(maxdate)]} {
|
||||
append str " and"
|
||||
}
|
||||
}
|
||||
if {[info exists FORM(maxdate)]} {
|
||||
set max $FORM(maxdate)
|
||||
append str " before [fmtclock $max "%m/%d %H:%M"]"
|
||||
}
|
||||
puts "<TITLE>$str</TITLE>"
|
||||
puts "<H1>$str</H1>"
|
||||
set list {}
|
||||
foreach i $checkinlist {
|
||||
upvar #0 $i info
|
||||
if {$info(date) >= $min && $info(date) <= $max} {
|
||||
lappend list $i
|
||||
}
|
||||
}
|
||||
} else {
|
||||
puts "<TITLE>All checkins</TITLE>"
|
||||
puts "<H1>All Checkins</H1>"
|
||||
set list $checkinlist
|
||||
}
|
||||
|
||||
if {$readonly} {
|
||||
puts "<h2><font color=red>Be aware that you are looking at an old hook!</font></h2>"
|
||||
}
|
||||
|
||||
|
||||
puts "(Current sort is by <tt>$FORM(sort)</tt>; click on a column header
|
||||
to sort by that column.)"
|
||||
|
||||
# Oh, boy, is this ever gross. Dynamically write some code to be the sort
|
||||
# comparison routine, so that we know that the sort code will run fast.
|
||||
|
||||
set fields [split $FORM(sort) ","]
|
||||
set w [lsearch $fields "date"]
|
||||
if {$w >= 0} {
|
||||
set fields [lrange $fields 0 [expr $w - 1]]
|
||||
}
|
||||
|
||||
set body {
|
||||
upvar #0 $n1 a $n2 b
|
||||
}
|
||||
foreach i $fields {
|
||||
append body "set delta \[string compare \$a($i) \$b($i)\]"
|
||||
append body "\n"
|
||||
append body {if {$delta != 0} {return $delta}}
|
||||
append body "\n"
|
||||
}
|
||||
append body {return [expr $b(date) - $a(date)]}
|
||||
|
||||
eval [list proc Compare {n1 n2} $body]
|
||||
|
||||
set total_added 0
|
||||
set total_removed 0
|
||||
|
||||
#
|
||||
# Calculate delta information
|
||||
#
|
||||
if {$delta_size} {
|
||||
foreach i $list {
|
||||
upvar #0 $i info
|
||||
set info(added) 0
|
||||
set info(removed) 0
|
||||
|
||||
#
|
||||
# Loop through the checkins, grab the filename and stickyflags
|
||||
#
|
||||
if {[info exists info(fullinfo)]} {
|
||||
foreach fu $info(fullinfo) {
|
||||
set fn [lindex $fu 0]
|
||||
set sticky [lindex $fu 4]
|
||||
|
||||
#
|
||||
# if the file is binary, don't show the delta information
|
||||
#
|
||||
if { ![string match {*.gif} $fn]
|
||||
&& ![string match {*.bmp} $fn]
|
||||
&& ![string match {-kb} $sticky]} {
|
||||
scan [lindex $fu 2] {%d} file_added
|
||||
scan [lindex $fu 3] {%d} file_removed
|
||||
if {[info exists file_added] && [info exists file_removed]} {
|
||||
incr info(added) $file_added
|
||||
incr info(removed) $file_removed
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set info(lines_changed) [format "%7d" [expr 1000000 - ($info(added) - $info(removed))]]
|
||||
incr total_added $info(added)
|
||||
incr total_removed $info(removed)
|
||||
}
|
||||
}
|
||||
|
||||
set list [lsort -command Compare $list]
|
||||
|
||||
regsub -all {[&?]sort=[^&]*} $buffer {} otherparams
|
||||
|
||||
proc NewSort {key} {
|
||||
global otherparams FORM
|
||||
set list [split $FORM(sort) ","]
|
||||
set w [lsearch $list $key]
|
||||
if {$w >= 0} {
|
||||
set list [lreplace $list $w $w]
|
||||
}
|
||||
set list [linsert $list 0 $key]
|
||||
return "[set otherparams]&sort=[join $list ,]"
|
||||
}
|
||||
|
||||
|
||||
if {$tweak} {
|
||||
puts "<FORM method=get action=\"dotweak.cgi\">"
|
||||
}
|
||||
|
||||
|
||||
puts "
|
||||
<TABLE border cellspacing=2>
|
||||
<TR ALIGN=LEFT>
|
||||
"
|
||||
|
||||
if {$tweak} {
|
||||
puts "<TH></TH>"
|
||||
}
|
||||
|
||||
puts "
|
||||
<TH><A HREF=\"showcheckins.cgi?[set otherparams]&sort=date\">When</A>
|
||||
<TH><A HREF=\"showcheckins.cgi?[NewSort treeopen]\">Tree state</A>
|
||||
<TH><A HREF=\"showcheckins.cgi?[NewSort person]\">Who</A>
|
||||
<TH><A HREF=\"showcheckins.cgi?[NewSort dir]\">Directory</A>
|
||||
<TH><A HREF=\"showcheckins.cgi?[NewSort files]\">Files</A>"
|
||||
|
||||
if {$delta_size} {
|
||||
puts "<TH><A HREF=\"showcheckins.cgi?[NewSort lines_changed]\"><tt>+/-</tt></A>"
|
||||
}
|
||||
|
||||
puts "
|
||||
<TH WIDTH=100%>Description
|
||||
</TR>"
|
||||
|
||||
set count 0
|
||||
set maxcount 100
|
||||
|
||||
set branchpart {}
|
||||
|
||||
if {![cequal $treeinfo($treeid,branch) {}]} {
|
||||
set branchpart "&branch=$treeinfo($treeid,branch)"
|
||||
}
|
||||
|
||||
foreach i $list {
|
||||
upvar #0 $i info
|
||||
incr count
|
||||
if {$count >= $maxcount} {
|
||||
set count 0
|
||||
# Don't make tables too big, or toy computers will break.
|
||||
puts "</TABLE><TABLE border cellspacing=2>"
|
||||
}
|
||||
puts "<TR>"
|
||||
if {$tweak} {
|
||||
puts "<TD><INPUT TYPE=CHECKBOX NAME=$i></TD>"
|
||||
}
|
||||
puts "<TD><a href=editcheckin.cgi?id=$i[BatchIdPart]>"
|
||||
puts "[fmtclock $info(date) "<font size=-2>%m/%d %H:%M</font>"]</a></TD>"
|
||||
puts "<TD>"
|
||||
if {$info(treeopen)} {
|
||||
puts "open"
|
||||
} else {
|
||||
puts "CLOSED"
|
||||
}
|
||||
if {[info exists info(notes)]} {
|
||||
if {![cequal $info(notes) ""]} {
|
||||
puts "<br>$info(notes)"
|
||||
}
|
||||
}
|
||||
puts "</TD>"
|
||||
set peoplearray($info(person)) 1
|
||||
puts "<TD><a href=\"http://phonebook/ds/dosearch/phonebook/uid=[url_quote "$info(person),ou=People,o= Netscape Communications Corp.,c=US"]\">$info(person)</a></TD>"
|
||||
puts "<TD><a href=\"cvsview2.cgi?root=$treeinfo($treeid,repository)&subdir=$info(dir)&files=[join $info(files) +]&command=DIRECTORY$branchpart\">[BreakBig $info(dir)]</a></TD>"
|
||||
puts "<TD>"
|
||||
foreach f $info(files) {
|
||||
puts "<a href=\"cvsview2.cgi?root=$treeinfo($treeid,repository)&subdir=$info(dir)&files=$f&command=DIRECTORY$branchpart\">$f</a>"
|
||||
}
|
||||
|
||||
puts "</TD>"
|
||||
if {$delta_size} {
|
||||
puts "<TD>"
|
||||
if {$info(removed) < 0} {
|
||||
set str_removed $info(removed)
|
||||
} else {
|
||||
set str_removed "-0"
|
||||
}
|
||||
puts "<tt>+$info(added)<br>$str_removed"
|
||||
puts "</TD>"
|
||||
}
|
||||
if {[info exists info(fullinfo)]} {
|
||||
foreach f $info(fullinfo) {
|
||||
lassign $f file version
|
||||
append versioninfo "$info(person)|$info(dir)|$file|$version,"
|
||||
}
|
||||
}
|
||||
puts "<TD WIDTH=100%>$info(log)</TD>"
|
||||
puts "</TR>"
|
||||
}
|
||||
puts "</TABLE>"
|
||||
|
||||
|
||||
if {$delta_size} {
|
||||
set deltastr " Lines changed <tt>($total_added/$total_removed)</tt>."
|
||||
} else {
|
||||
set deltastr ""
|
||||
}
|
||||
|
||||
|
||||
puts "[llength $list] checkins listed. $deltastr"
|
||||
|
||||
|
||||
if {$tweak} {
|
||||
puts "
|
||||
<hr>
|
||||
Check the checkins you wish to affect. Then select one of the below options.
|
||||
And type the magic word. Then click on submit.
|
||||
<P>
|
||||
<INPUT TYPE=HIDDEN NAME=treeid VALUE=$treeid>
|
||||
<INPUT TYPE=radio NAME=command VALUE=nuke>Delete these checkins.<BR>
|
||||
<INPUT TYPE=radio NAME=command VALUE=setopen>Set the tree state on these checkins to be <B>Open</B>.<BR>
|
||||
<INPUT TYPE=radio NAME=command VALUE=setclose>Set the tree state on these checkins to be <B>Closed</B>.<BR>
|
||||
<INPUT TYPE=radio NAME=command VALUE=movetree>Move these checkins over to this tree:
|
||||
<SELECT NAME=desttree SIZE=1>"
|
||||
|
||||
proc IsSelected {value} {
|
||||
global treeid
|
||||
if {[cequal $value $treeid]} {
|
||||
return "SELECTED"
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
foreach i $treelist {
|
||||
if {![info exists treeinfo($i,nobonsai)]} {
|
||||
puts "<OPTION [IsSelected $i] VALUE=$i>$treeinfo($i,description)"
|
||||
}
|
||||
}
|
||||
|
||||
puts "</SELECT><P>
|
||||
<B>Password:</B><INPUT NAME=password TYPE=password></td>
|
||||
<BR>
|
||||
<INPUT TYPE=SUBMIT VALUE=Submit>
|
||||
</FORM>"
|
||||
} else {
|
||||
puts " "
|
||||
puts "<a href=showcheckins.cgi?$buffer&tweak=1>Tweak some of these checkins.</a>"
|
||||
puts "<br><br>"
|
||||
puts "<FORM action='multidiff.cgi' method=post>"
|
||||
puts "<INPUT TYPE='HIDDEN' name='allchanges' value = '$versioninfo'>"
|
||||
puts "<INPUT TYPE=SUBMIT VALUE='Show me ALL the Diffs'>"
|
||||
puts "</FORM>"
|
||||
}
|
||||
|
||||
if {[info exists FORM(ltabbhack)]} {
|
||||
puts "<!-- StupidLloydHack [join [lsort [array names peoplearray]] {,}] -->"
|
||||
puts "<!-- LloydHack2 $versioninfo -->"
|
||||
}
|
||||
|
||||
|
||||
PutsTrailer
|
|
@ -0,0 +1,54 @@
|
|||
#!/usr/bonsaitools/bin/mysqltcl
|
||||
# -*- Mode: tcl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
source CGI.tcl
|
||||
|
||||
LoadTreeConfig
|
||||
|
||||
proc IsChecked {value} {
|
||||
global treeid
|
||||
if {[cequal $value $treeid]} {
|
||||
return "CHECKED"
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
puts "Content-type: text/html
|
||||
|
||||
<HTML>
|
||||
<TITLE>George, George, George of the jungle...</TITLE>
|
||||
|
||||
Which tree would you like to see?
|
||||
"
|
||||
|
||||
puts "<FORM method=get action=\"toplevel.cgi\">"
|
||||
|
||||
foreach i $treelist {
|
||||
if {![info exists treeinfo($i,nobonsai)]} {
|
||||
puts "<INPUT TYPE=radio NAME=treeid VALUE=$i [IsChecked $i]>"
|
||||
puts "$treeinfo($i,description)<BR>"
|
||||
}
|
||||
}
|
||||
|
||||
puts "<INPUT TYPE=SUBMIT Value=\"Submit\"></FORM>"
|
||||
|
||||
PutsTrailer
|
||||
|
||||
exit
|
|
@ -0,0 +1,12 @@
|
|||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
|
||||
require 'utils.pl';
|
||||
|
||||
Lock();
|
||||
|
||||
print "Got lock.\n";
|
||||
|
||||
sleep 10;
|
||||
|
||||
Unlock();
|
|
@ -0,0 +1,261 @@
|
|||
#!/usr/bonsaitools/bin/mysqltcl
|
||||
# -*- Mode: tcl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
source CGI.tcl
|
||||
|
||||
Lock
|
||||
LoadCheckins
|
||||
LoadMOTD
|
||||
LoadWhiteboard
|
||||
LoadTreeConfig
|
||||
Unlock
|
||||
|
||||
|
||||
if {$treeopen} {
|
||||
set openword Open
|
||||
} else {
|
||||
set openword Closed
|
||||
}
|
||||
|
||||
puts "Content-type: text/html
|
||||
Refresh: 300
|
||||
|
||||
<HTML>
|
||||
<TITLE>($openword) Bonsai -- the art of effectively controlling trees</TITLE>
|
||||
|
||||
<IMG ALIGN=right SRC=bonsai.gif>
|
||||
<H1>Bonsai -- Tree Control</H1>
|
||||
|
||||
<FORM name=treeform>
|
||||
<H3>
|
||||
<SELECT name=treeid size=1 onchange='submit();'>
|
||||
"
|
||||
|
||||
# <SELECT name=treeid size=1 onchange='window.location =\"toplevel.cgi?treeid=\" + treeform.treeid.value;'>
|
||||
|
||||
foreach t $treelist {
|
||||
if {![info exists treeinfo($t,nobonsai)]} {
|
||||
if {[cequal $t $treeid]} {
|
||||
set c "SELECTED"
|
||||
} else {
|
||||
set c ""
|
||||
}
|
||||
puts "<OPTION VALUE=$t $c>$treeinfo($t,description)"
|
||||
}
|
||||
}
|
||||
|
||||
puts "</SELECT></H3></FORM>"
|
||||
|
||||
|
||||
|
||||
if {$readonly} {
|
||||
puts "<h2><font color=red>Be aware that you are looking at an old hook!</font></h2>"
|
||||
}
|
||||
|
||||
puts "<tt>[fmtclock [getclock] "%R"]</tt>: The tree is currently <B>"
|
||||
|
||||
if {$treeopen} {
|
||||
puts "<FONT SIZE=+2>OPEN</FONT></B><BR>"
|
||||
} else {
|
||||
puts "<FONT SIZE=+3 COLOR=RED>CLOSED</FONT></B><BR>"
|
||||
}
|
||||
|
||||
if {!$treeopen} {
|
||||
puts "The tree has been closed since <tt>[MyFmtClock $closetimestamp]</tt>."
|
||||
}
|
||||
puts "<BR>"
|
||||
puts "The last known good tree had a timestamp "
|
||||
puts "of <tt>[fmtclock $lastgoodtimestamp "%D %T %Z"]</tt>.<br>"
|
||||
|
||||
puts "<hr><pre variable>$motd</pre><hr>"
|
||||
|
||||
|
||||
puts "<br clear=all>"
|
||||
|
||||
# if {[info exists FORM(whitedelta)]} {
|
||||
# set delta $FORM(whitedelta)
|
||||
# } else {
|
||||
# set delta [expr 24 * 60 * 60]
|
||||
# }
|
||||
#
|
||||
# set fileok 0
|
||||
# set filename [DataDir]/whitedelta-$delta
|
||||
# if {[file exists $filename]} {
|
||||
# if {[file mtime $filename] > [file mtime [DataDir]/whiteboard]} {
|
||||
# set fileok 1
|
||||
# }
|
||||
# }
|
||||
#
|
||||
# if {!$fileok} {
|
||||
# set tmp [DataDir]/tmpwhite.[id process]
|
||||
# Lock
|
||||
# set date [fmtclock [expr [getclock] - $delta] "%a %b %d %H:%M:%S LT %Y"]
|
||||
# catch {exec co -q -d$date -p [DataDir]/whiteboard > $tmp 2> /dev/null}
|
||||
# catch {chmod 0666 $tmp}
|
||||
# exec ./changebar.tcl $tmp [DataDir]/whiteboard > $filename
|
||||
# unlink $tmp
|
||||
# catch {chmod 0666 $filename}
|
||||
# Unlock
|
||||
# }
|
||||
|
||||
|
||||
#puts "<b><a href=editwhiteboard.cgi[BatchIdPart ?]>Free-for-all whiteboard:</a></b> (Changebars indicate changes within last [PrettyDelta $delta])<pre>[html_quote [read_file $filename]]</pre><hr>"
|
||||
|
||||
puts "<b><a href=editwhiteboard.cgi[BatchIdPart ?]>Free-for-all whiteboard:</a></b><pre>[html_quote $whiteboard]</pre><hr>"
|
||||
|
||||
|
||||
foreach c $checkinlist {
|
||||
upvar #0 $c info
|
||||
lappend people($info(person)) $c
|
||||
if {!$info(treeopen)} {
|
||||
lappend closedcheckin($info(person)) $c
|
||||
}
|
||||
}
|
||||
|
||||
if {[info exists people]} {
|
||||
|
||||
puts "The following people are on \"the hook\", since they have made"
|
||||
puts "checkins to the tree since it last opened: "
|
||||
puts "<p>"
|
||||
|
||||
set peoplelist [lsort [array names people]]
|
||||
|
||||
set query "(| "
|
||||
foreach p $peoplelist {
|
||||
append query "(mail=$p@netscape.com) "
|
||||
set fullname($p) ""
|
||||
set curcontact($p) ""
|
||||
}
|
||||
append query ")"
|
||||
|
||||
set ldaperror 0
|
||||
|
||||
if {[catch {set fid [open "|./data/ldapsearch -b \"o=Netscape Communications Corp.,c=US\" -h $ldapserver -p $ldapport -s sub -S mail \"$query\" mail cn nscpcurcontactinfo" r]} errvar]} {
|
||||
set ldaperror 1
|
||||
} else {
|
||||
set doingcontactinfo 0
|
||||
while {[gets $fid line] >= 0} {
|
||||
if {$doingcontactinfo} {
|
||||
if {[regexp -- {^ (.*)$} $line foo n]} {
|
||||
append curcontact($curperson) $n
|
||||
continue
|
||||
}
|
||||
set doingcontactinfo 0
|
||||
}
|
||||
if {[regexp -- {^mail: (.*)@} $line foo n]} {
|
||||
set curperson $n
|
||||
} elseif {[regexp -- {^cn: (.*)$} $line foo n]} {
|
||||
set fullname($curperson) $n
|
||||
} elseif {[regexp -- {^nscpcurcontactinfo: (.*)$} $line foo n]} {
|
||||
set curcontact($curperson) $n
|
||||
set doingcontactinfo 1
|
||||
}
|
||||
}
|
||||
if {[catch {close $fid} errvar]} {
|
||||
set ldaperror 1
|
||||
}
|
||||
}
|
||||
|
||||
if {$ldaperror} {
|
||||
puts "<font color=red>Can't contact the directory server at $ldapserver:$ldapport -- $errvar</font>"
|
||||
}
|
||||
|
||||
puts "<table border cellspacing=2>"
|
||||
puts "<th colspan=2>Who</th><th>What</th><th>How to contact</th>"
|
||||
|
||||
foreach p $peoplelist {
|
||||
if {[info exists closedcheckin($p)]} {
|
||||
set extra " <font color=red>([llength $closedcheckin($p)] while tree closed!)</font>"
|
||||
} else {
|
||||
set extra ""
|
||||
}
|
||||
|
||||
puts "
|
||||
<tr>
|
||||
<td>$fullname($p)</a></td>
|
||||
<td><a href=\"http://phonebook/ds/dosearch/phonebook/uid=[url_quote "$p,ou=People,o= Netscape Communications Corp.,c=US"]\">
|
||||
$p</td>
|
||||
<td><a href=\"showcheckins.cgi?person=$p[BatchIdPart]\">[llength $people($p)]
|
||||
[Pluralize change [llength $people($p)]]</a>$extra</td>"
|
||||
puts "
|
||||
<td>$curcontact($p)
|
||||
</tr>"
|
||||
}
|
||||
|
||||
puts "</table>"
|
||||
puts "[llength $checkinlist] checkins."
|
||||
|
||||
if {[cequal $treeid default]} {
|
||||
set mailaddr "bonsai-hook"
|
||||
} else {
|
||||
set f [open data/$treeid/hooklist r]
|
||||
set fileEOF [gets $f hookentry]
|
||||
set theHookList {}
|
||||
while { $fileEOF != -1 } {
|
||||
set theHookList [concat $theHookList $hookentry]
|
||||
set fileEOF [gets $f hookentry]
|
||||
}
|
||||
set mailaddr "$theHookList"
|
||||
}
|
||||
puts "<p>"
|
||||
puts "<a href=showcheckins.cgi[BatchIdPart ?]>Show all checkins.</a><br>"
|
||||
if {[cequal $treeid default]} {
|
||||
puts "<a href=\"mailto:[set mailaddr]@warp?subject=Build problem\">"
|
||||
} else {
|
||||
puts "<a href=\"mailto:[set mailaddr]?subject=Build problem\">"
|
||||
}
|
||||
puts "Send mail to \"the hook\".</a><br>"
|
||||
} else {
|
||||
puts "Nobody seems to have made any changes since the tree opened."
|
||||
}
|
||||
|
||||
|
||||
set cvsqueryurl "cvsqueryform.cgi?cvsroot=$treeinfo($treeid,repository)&module=$treeinfo($treeid,module)"
|
||||
if {[clength $treeinfo($treeid,branch)] > 0} {
|
||||
append cvsqueryurl "&branch=$treeinfo($treeid,branch)"
|
||||
}
|
||||
|
||||
puts "
|
||||
<hr>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Useful links </th><th width=10%></th><th>Help corner</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign=top>
|
||||
<a href=$cvsqueryurl><b>CVS Query Tool</b></a><br>
|
||||
<a href=http://warp/tinderbox/showbuilds.cgi>Tinderbox continuous builds</a><br>
|
||||
<a href=\"switchtree.cgi[BatchIdPart ?]\">Switch to look at a different tree or branch</a><br>
|
||||
<a href=\"news:mcom.dev.client.build.busted\">Look at the Busted Tree Newsgroup</a><br>
|
||||
<a href=http://phonebook/>Look up someone in the phonebook.</a><br>
|
||||
<a href=viewold.cgi[BatchIdPart ?]>Time warp -- view a different day's hook.</a><br>
|
||||
<a href=countcheckins.cgi[BatchIdPart ?]>See some stupid statistics about recent checkins.</a><br>
|
||||
<a href=admin.cgi[BatchIdPart ?]>Administration menu.</a><br>
|
||||
</td><td>
|
||||
</td><td valign=top>
|
||||
<a href=index.html>Introduction to Bonsai.</a><br>
|
||||
<a href=http://warp/client/dogbert/tree.html>Overview of our source tree strategy.</a><br>
|
||||
<a href=contacthelp.html>Changing someone else's contact info (yes you can!)</a><br>
|
||||
<a href=http://warp/client/dogbert/buildlore/index.html>Dogbert build lore</a>
|
||||
</td>
|
||||
</tr></table>
|
||||
"
|
||||
|
||||
|
||||
exit
|
|
@ -0,0 +1,7 @@
|
|||
#include <stdio.h>
|
||||
#include <crypt.h>
|
||||
|
||||
main(int argc, char** argv) {
|
||||
printf("%s\n", crypt(argv[1], "aa"));
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
use Mysql;
|
||||
|
||||
require 'header.pl';
|
||||
|
||||
$lockcount = 0;
|
||||
|
||||
1;
|
||||
|
||||
|
||||
sub Lock {
|
||||
if ($lockcount <= 0) {
|
||||
$lockcount = 0;
|
||||
if (!open(LOCKFID, ">>data/lockfile")) {
|
||||
mkdir "data", 0777;
|
||||
chmod 0777, "data";
|
||||
open(LOCKFID, ">>data/lockfile") || die "Can't open lockfile.";
|
||||
}
|
||||
my $val = flock(LOCKFID,2);
|
||||
if (!$val) { # '2' is magic 'exclusive lock' const.
|
||||
print "Lock failed: $val\n";
|
||||
}
|
||||
chmod 0666, "data/lockfile";
|
||||
}
|
||||
$lockcount++;
|
||||
}
|
||||
|
||||
sub Unlock {
|
||||
$lockcount--;
|
||||
if ($lockcount <= 0) {
|
||||
flock(LOCKFID,8); # '8' is magic 'unlock' const.
|
||||
close LOCKFID;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub loadConfigData {
|
||||
if (@treelist > 0) {return;}
|
||||
local($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
|
||||
$atime,$pmtime,$ctime,$blksize,$blocks) = stat("data/configdata.pl");
|
||||
local $tmtime;
|
||||
($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
|
||||
$atime,$tmtime,$ctime,$blksize,$blocks) = stat("data/configdata");
|
||||
|
||||
if ($pmtime eq "" || $pmtime < $tmtime) {
|
||||
system "./perlifyconfig.tcl";
|
||||
}
|
||||
|
||||
open(CONFIGDATA, "<data/configdata.pl") || die "Can't open configdata.pl";
|
||||
while (<CONFIGDATA>) {
|
||||
eval;
|
||||
}
|
||||
close CONFIGDATA;
|
||||
}
|
||||
|
||||
|
||||
sub pickDefaultRepository {
|
||||
loadConfigData();
|
||||
return $treeinfo{$treelist[0]}->{'repository'};
|
||||
}
|
||||
|
||||
|
||||
sub getRepositoryList {
|
||||
loadConfigData();
|
||||
my @result = ();
|
||||
TREELOOP: foreach my $i (@treelist) {
|
||||
my $r = $treeinfo{$i}->{'repository'};
|
||||
foreach my $j (@result) {
|
||||
if ($j eq $r) {
|
||||
next TREELOOP;
|
||||
}
|
||||
}
|
||||
push @result, $r;
|
||||
}
|
||||
return @result;
|
||||
}
|
||||
|
||||
|
||||
sub validateRepository {
|
||||
my ($root) = @_;
|
||||
my @list = getRepositoryList();
|
||||
foreach my $r (@list) {
|
||||
if ($r eq $root) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
print "Invalid repository $root selected. Send mail to terry\@netscape.com if you think this should have worked.\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
sub ConnectToDatabase {
|
||||
if ($dbh == "") {
|
||||
$dbh = Mysql->Connect("localhost") || die "Can't connect to database server -- $Mysql::db_errstr";
|
||||
$dbh->SelectDB("bonsai") || die "Can't select bonsai database";
|
||||
}
|
||||
return $dbh;
|
||||
}
|
||||
|
||||
|
||||
sub formatSqlTime {
|
||||
my $when = @_[0];
|
||||
my($sec,$minute,$hour,$mday,$mon,$year) = localtime( $when );
|
||||
return sprintf("%04d-%02d-%02d %02d:%02d:%02d",
|
||||
$year + 1900, $mon + 1, $mday,
|
||||
$hour, $minute, $sec);
|
||||
}
|
||||
|
||||
|
||||
sub SqlQuote {
|
||||
$_ = @_[0];
|
||||
s/'/''/g;
|
||||
s/\\/\\\\/g;
|
||||
return $_;
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
#!/usr/bonsaitools/bin/mysqltcl
|
||||
# -*- Mode: tcl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Bonsai CVS tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
source CGI.tcl
|
||||
|
||||
LoadCheckins
|
||||
|
||||
proc IsChecked {value} {
|
||||
global batchid
|
||||
if {[cequal $value $batchid]} {
|
||||
return "CHECKED"
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
puts "Content-type: text/html
|
||||
|
||||
<HTML>
|
||||
<TITLE>Let's do the time warp again...</TITLE>
|
||||
|
||||
Which hook would you like to see?
|
||||
"
|
||||
|
||||
set list {}
|
||||
|
||||
|
||||
foreach i [glob "[DataDir]/batch-*\[0-9\]"] {
|
||||
regexp -- {[0-9]*$} $i num
|
||||
lappend list $num
|
||||
}
|
||||
|
||||
set list [lsort -integer -decreasing $list]
|
||||
|
||||
puts "<FORM method=get action=\"toplevel.cgi\">"
|
||||
puts "<INPUT TYPE=HIDDEN NAME=treeid VALUE=$treeid>"
|
||||
puts "<INPUT TYPE=SUBMIT Value=\"Submit\"><BR>"
|
||||
|
||||
set value [lvarpop list]
|
||||
|
||||
puts "<INPUT TYPE=radio NAME=batchid VALUE=$value [IsChecked $value]>"
|
||||
puts "The current hook.<BR>"
|
||||
|
||||
set count 1
|
||||
foreach i $list {
|
||||
set value [lvarpop list]
|
||||
puts "<INPUT TYPE=radio NAME=batchid VALUE=$value [IsChecked $value]>"
|
||||
source [DataDir]/batch-$i
|
||||
puts "Hook for tree that closed on [MyFmtClock $closetimestamp] <BR>"
|
||||
}
|
||||
|
||||
puts "<INPUT TYPE=SUBMIT Value=\"Submit\">"
|
||||
puts "</FORM>"
|
||||
|
||||
PutsTrailer
|
||||
|
||||
exit
|
|
@ -0,0 +1,102 @@
|
|||
#!/usr/bonsaitools/bin/perl
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Application Registry.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
require 'lloydcgi.pl';
|
||||
$|=1;
|
||||
|
||||
$filename= $form{"file"};
|
||||
$dirname= $form{"dir"};
|
||||
$branch= $form{"branch"};
|
||||
$cvsroot= $form{"cvsroot"};
|
||||
$rev= $form{"rev"};
|
||||
$prev_rev= $form{"prev_rev"};
|
||||
$linked_text= $form{"linked_text"};
|
||||
$linked_text = $filename if $linked_text eq '';
|
||||
|
||||
$branch = $rev if $branch eq '' && $rev =~ /[A-Za-z]/;
|
||||
|
||||
@extra_url = ();
|
||||
@extra_text = ();
|
||||
|
||||
print "Content-type: text/html\n\n<HTML>\n";
|
||||
|
||||
print "<table border=1 cellspacing=1 cellpadding=3><tr><td>\n";
|
||||
|
||||
&load_extra_data;
|
||||
|
||||
|
||||
$i = 0;
|
||||
while( $i < @extra_text ){
|
||||
$t = $extra_text[$i];
|
||||
if( $u = $extra_url[$i] ){
|
||||
|
||||
print("<dt><a href=$u>$t</a>\n");
|
||||
}
|
||||
else {
|
||||
print("<dt>$t\n");
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
|
||||
if( @extra_text ){
|
||||
print("<hr>\n");
|
||||
}
|
||||
|
||||
|
||||
$dirname2 = $dirname;
|
||||
|
||||
$dirname2 =~ s/^ns\///;
|
||||
|
||||
print "
|
||||
$linked_text
|
||||
<SPACER TYPE=VERTICAL SIZE=5>
|
||||
<dt><A HREF=../bonsai/cvsblame.cgi?file=$dirname/$filename&rev=$rev&root=$cvsroot>
|
||||
View Blame-Annotated Source</A>
|
||||
";
|
||||
if ($prev_rev ne '') {
|
||||
print "<dt><A HREF='../bonsai/cvsview2.cgi"
|
||||
."?diff_mode=context&whitespace_mode=show"
|
||||
."&root=$cvsroot&subdir=$dirname&command=DIFF_FRAMESET&file=$filename"
|
||||
."&rev1=$rev&rev2=$prev_rev'>View Diff $prev_rev vs. $rev</A>";
|
||||
} else {
|
||||
|
||||
print "<dt><A HREF='../bonsai/cvsview2.cgi?subdir=$dirname"
|
||||
."\&files=$filename\&command=DIRECTORY&branch=$branch&root=$cvsroot'>"
|
||||
."View Diff's</A>";
|
||||
}
|
||||
|
||||
print "<DT><A HREF='../bonsai/cvslog.cgi?file=$dirname/$filename&rev=$rev&root=$cvsroot'>
|
||||
View Logs</A>
|
||||
";
|
||||
|
||||
print "
|
||||
</td></tr></table>";
|
||||
|
||||
sub load_extra_data {
|
||||
local( $i, $u, $t );
|
||||
|
||||
$i = 0;
|
||||
while( ($u = $form{"u${i}"}) ne "" || $form{"t${i}"} ne "" ) {
|
||||
$t = $form{"t${i}"};
|
||||
if( $t eq "" ) {$t = $u };
|
||||
$extra_url[$i] = $u;
|
||||
$extra_text[$i] = $t;
|
||||
$i++;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Application Registry.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
&split_cgi_args;
|
||||
1;
|
||||
|
||||
sub split_cgi_args {
|
||||
local($i,$var,$value, $s);
|
||||
|
||||
if( $ENV{"REQUEST_METHOD"} eq 'POST'){
|
||||
while(<> ){
|
||||
$s .= $_;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$s = $ENV{"QUERY_STRING"};
|
||||
}
|
||||
|
||||
@args= split(/\&/, $s );
|
||||
|
||||
for $i (@args) {
|
||||
($var, $value) = split(/=/, $i);
|
||||
$var =~ tr/+/ /;
|
||||
$var =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
|
||||
$value =~ tr/+/ /;
|
||||
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
|
||||
$form{$var} = $value;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
#!/usr/bonsaitools/bin/perl
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Application Registry.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
require 'lloydcgi.pl';
|
||||
$|=1;
|
||||
|
||||
$email= $form{"email"};
|
||||
$full_name = $email;
|
||||
$enc_full_name = $email; #this should be url encoded
|
||||
|
||||
@extra_url = ();
|
||||
@extra_text = ();
|
||||
|
||||
print "Content-type: text/html\n\n<HTML>\n";
|
||||
|
||||
print "<table border=1 cellspacing=1 cellpadding=3><tr><td>\n";
|
||||
print "$email\n";
|
||||
print "<SPACER TYPE=VERTICAL SIZE=5>\n";
|
||||
|
||||
&load_extra_data;
|
||||
|
||||
|
||||
$i = 0;
|
||||
while( $i < @extra_text ){
|
||||
$t = $extra_text[$i];
|
||||
if( $u = $extra_url[$i] ){
|
||||
|
||||
print("<dt><a href=$u>$t</a>\n");
|
||||
}
|
||||
else {
|
||||
print("<dt>$t\n");
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
|
||||
if( @extra_text ){
|
||||
print("<hr>\n");
|
||||
}
|
||||
|
||||
print "
|
||||
<dt><A HREF='mailto:$email\@netscape.com'>
|
||||
Send Mail</A>
|
||||
|
||||
|
||||
|
||||
<dt><A HREF='../bonsai/cvsquery.cgi?module=all&branch=&dir=&file=&who=$email&sortby=Date&hours=2&date=week&mindate=&maxdate='>
|
||||
Check-ins within 7 days</A>
|
||||
|
||||
</table>
|
||||
|
||||
<form method='post' name='aka' action='http://aka/aka/snoop-reverse-cache.cgi'>
|
||||
<input type=hidden name=alias value='$email'> </form>
|
||||
";
|
||||
|
||||
sub load_extra_data {
|
||||
local( $i, $u, $t );
|
||||
|
||||
$i = 0;
|
||||
while( ($u = $form{"u${i}"}) ne "" || $form{"t${i}"} ne "" ) {
|
||||
$t = $form{"t${i}"};
|
||||
if( $t eq "" ) {$t = $u };
|
||||
$extra_url[$i] = $u;
|
||||
$extra_text[$i] = $t;
|
||||
$i++;
|
||||
}
|
||||
}
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 13 KiB |
|
@ -0,0 +1 @@
|
|||
<font size=+2>Click on the <b>filename and line number</b> in the log and the source will appear in this window.</font>
|
|
@ -0,0 +1,73 @@
|
|||
This is Tinderbox. See <http://www.mozilla.org/tinderbox.html>.
|
||||
|
||||
|
||||
==========
|
||||
DISCLAIMER
|
||||
==========
|
||||
|
||||
This is not very well packaged code. It's not packaged at all. Don't
|
||||
come here expecting something you plop in a directory, twiddle a few
|
||||
things, and you're off and using it. Much work has to be done to get
|
||||
there. I'd like to get there, but it wasn't clear when that would be,
|
||||
and so we decided to let people see it first.
|
||||
|
||||
Don't believe for a minute that you can use this stuff without first
|
||||
understanding most of the code.
|
||||
|
||||
|
||||
|
||||
============
|
||||
DEPENDENCIES
|
||||
============
|
||||
|
||||
To use tinderbox, you must first have bonsai up and running.
|
||||
See <http://www.mozilla.org/bonsai.html>.
|
||||
|
||||
Be warned now that bonsai is not easily installed.
|
||||
|
||||
|
||||
====================================
|
||||
What's What in the Tinderbox sources:
|
||||
====================================
|
||||
|
||||
|
||||
1afi003r.gif The "flames" animation used by ???
|
||||
|
||||
Empty.html Document used for an empty frame by ???
|
||||
|
||||
addimage.cgi The form that lets you add a new image to the list of
|
||||
images that Tinderbox picks from randomly.
|
||||
|
||||
addnote.cgi Add a note to a build log.
|
||||
|
||||
admintree.cgi Lets you perform various admin tasks on a Tinderbox tree.
|
||||
This just prompts for a password and posts to doadmin.cgi.
|
||||
|
||||
buildwho.pl ???
|
||||
clean.pl ???
|
||||
copydata.pl ???
|
||||
|
||||
doadmin.cgi Actually do the work to admin a tinderbox tree
|
||||
|
||||
ep_mac.pl Knows how to parse Mac build error logs. Used by ???
|
||||
ep_unix.pl Knows how to parse Unix build error logs. Used by ???
|
||||
ep_windows.pl Knows how to parse Windows build error logs. Used by ???
|
||||
|
||||
faq.html Wildly out of date.
|
||||
|
||||
fixupimages.pl ???
|
||||
globals.pl ???
|
||||
handlemail.pl ???
|
||||
imagelog.pl ???
|
||||
index.html ???
|
||||
processbuild.pl ???
|
||||
reledanim.gif ???
|
||||
|
||||
showbuilds.cgi The main Tinderbox page. Interesting params are:
|
||||
express=1; hours=n; tree2=anothertree.
|
||||
|
||||
showimages.cgi Show all the images in the Tinderbox list. Password-protected.
|
||||
|
||||
showlog.cgi Show a build log (brief and full).
|
||||
|
||||
star.gif The "star" image used to annotate builds by ???
|
|
@ -0,0 +1,402 @@
|
|||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
use Socket;
|
||||
|
||||
use lib "../bonsai";
|
||||
require 'header.pl';
|
||||
|
||||
print "Content-type: text/html\n\n";
|
||||
|
||||
EmitHtmlTitleAndHeader("tinderbox: add images", "add images");
|
||||
|
||||
$| = 1;
|
||||
|
||||
require "globals.pl";
|
||||
require "imagelog.pl";
|
||||
|
||||
&split_cgi_args;
|
||||
|
||||
|
||||
sub Error {
|
||||
my ($msg) = @_;
|
||||
print "<BR><BR><BR>";
|
||||
print "<UL><FONT SIZE='+1'><B>Something went wrong:</B><P>";
|
||||
print "<UL>";
|
||||
print $msg;
|
||||
print "</UL>";
|
||||
print "<P>";
|
||||
print "Hit <B>\`Back'</B> and try again.";
|
||||
print "</UL>";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
|
||||
if( $url = $form{"url"} ){
|
||||
$quote = $form{"quote"};
|
||||
|
||||
$quote =~ s/[\r\n]/ /g;
|
||||
$url =~ s/[\r\n]/ /g;
|
||||
|
||||
$width = "";
|
||||
$height = "";
|
||||
# I think we don't want to allow this --jwz
|
||||
# $width = $form{"width"};
|
||||
# $height = $form{"height"};
|
||||
|
||||
if ($width eq "" || $height eq "") {
|
||||
$size = &URLsize($url);
|
||||
if ($size =~ /WIDTH=([0-9]*)/) {
|
||||
$width = $1;
|
||||
}
|
||||
if ($size =~ /HEIGHT=([0-9]*)/) {
|
||||
$height = $1;
|
||||
}
|
||||
if ($width eq "" || $height eq "") {
|
||||
Error "Couldn't get image size for \"$url\".\n";
|
||||
}
|
||||
}
|
||||
|
||||
print "
|
||||
|
||||
<P><center><img border=2 src='$url' width=$width height=$height><br>
|
||||
<i>$quote</i><br><br>
|
||||
";
|
||||
|
||||
if( $form{"submit"} ne "Yes" ){
|
||||
my $u2 = $url;
|
||||
my $q2 = $quote;
|
||||
$u2 =~ s@&@&@g; $u2 =~ s@<@<@g; $u2 =~ s@\"@"@g;
|
||||
$q2 =~ s@&@&@g; $q2 =~ s@<@<@g; $q2 =~ s@\"@"@g;
|
||||
|
||||
print "
|
||||
<form action='addimage.cgi' METHOD='get'>
|
||||
<input type=hidden name=url value=\"$u2\">
|
||||
<input type=hidden name=quote value=\"$q2\">
|
||||
<HR>
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TH ALIGN=RIGHT NOWRAP>Image URL:</TH>
|
||||
<TD><TT><B>$u2</B></TT></TD>
|
||||
</TR><TR>
|
||||
<TH ALIGN=RIGHT>Caption:</TH>
|
||||
<TD><TT><B>$q2</B></TT></TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD></TD>
|
||||
<TD>
|
||||
<FONT SIZE=+2><B>
|
||||
Does that look right?
|
||||
<SPACER SIZE=10>
|
||||
<INPUT Type='submit' name='submit' value='Yes'>
|
||||
</B><BR>(If not, hit \`Back' and fix it.)
|
||||
</FONT>
|
||||
</TD>
|
||||
</TABLE>
|
||||
</form>
|
||||
";
|
||||
}
|
||||
else {
|
||||
&add_imagelog( $url, $quote, $width, $height );
|
||||
print "<br><br>
|
||||
<font size=+2>Has been added</font><br><br>
|
||||
<a href=showbuilds.cgi>Return to Log</a>";
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
print "
|
||||
<h2>Add an image and a funny caption.</h2>
|
||||
|
||||
<ul>
|
||||
<p>This is about fun, and making your daily excursion to
|
||||
<A HREF=http://www.mozilla.org/tinderbox.html>Tinderbox</A> a
|
||||
novel experience. Engineers spend a lot of time here; it might as well
|
||||
have some entertainment value.
|
||||
|
||||
<p>Please play nice. We don't have the time or inclination to look at
|
||||
everything you people submit, but if we get nastygrams or legalgrams
|
||||
and have to take something down, we will curse your IP address, and you
|
||||
might even make it so the whole thing goes away forever. Please don't
|
||||
make us go there. You might also avoid links to big images or slow
|
||||
servers.
|
||||
|
||||
<p><ul><B>Thank you for playing nice.</B></UL>
|
||||
|
||||
<p>If you really find an image offensive, please
|
||||
<A HREF=mailto:ltabb\@netscape.com?Subject=offensive%20image>tell us</A>
|
||||
nicely before someone causes a stink. Be sure to include the URL of
|
||||
the image. Remember, we don't screen these submissions and may not
|
||||
have even seen it.
|
||||
</ul>
|
||||
|
||||
<p><form action='addimage.cgi' METHOD='get'>
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TH ALIGN=RIGHT NOWRAP>Image URL:</TH>
|
||||
<TD><INPUT NAME='url' SIZE=60></TD>
|
||||
</TR><TR>
|
||||
<TH ALIGN=RIGHT>Caption:</TH>
|
||||
<TD><INPUT NAME='quote' SIZE=60></TD>
|
||||
</TR><TR>
|
||||
<TD></TD>
|
||||
<TD><B>
|
||||
<INPUT Type='submit' name='submit' value='Test'>
|
||||
<SPACER SIZE=25>
|
||||
<INPUT Type='reset' name='reset' value='Reset'>
|
||||
</B></TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
</form>
|
||||
<br><br>
|
||||
";
|
||||
}
|
||||
|
||||
sub split_cgi_args {
|
||||
local($i,$var,$value, $s);
|
||||
|
||||
$s = $ENV{"QUERY_STRING"};
|
||||
|
||||
@args= split(/\&/, $s );
|
||||
|
||||
for $i (@args) {
|
||||
($var, $value) = split(/=/, $i);
|
||||
$value =~ tr/+/ /;
|
||||
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
|
||||
$form{$var} = $value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#sub imgsize {
|
||||
# local($file)= @_;
|
||||
#
|
||||
# #first try to open the file
|
||||
# if( !open(STREAM, "<$file") ){
|
||||
# Error "Can't open IMG $file";
|
||||
## $size="";
|
||||
# } else {
|
||||
# if ($file =~ /.jpg/i || $file =~ /.jpeg/i) {
|
||||
# $size = &jpegsize(STREAM);
|
||||
# } elsif($file =~ /.gif/i) {
|
||||
# $size = &gifsize(STREAM);
|
||||
# } elsif($file =~ /.xbm/i) {
|
||||
# $size = &xbmsize(STREAM);
|
||||
# } else {
|
||||
# return "";
|
||||
# }
|
||||
# $_ = $size;
|
||||
# if( /\s*width\s*=\s*([0-9]*)\s*/i ){
|
||||
# ($newwidth)= /\s*width\s*=\s*(\d*)\s*/i;
|
||||
# }
|
||||
# if( /\s*height\s*=\s*([0-9]*)\s*/i ){
|
||||
# ($newheight)=/\s*height\s*=\s*(\d*)\s*/i;
|
||||
# }
|
||||
# close(STREAM);
|
||||
# }
|
||||
# return $size;
|
||||
#}
|
||||
|
||||
###########################################################################
|
||||
# Subroutine gets the size of the specified GIF
|
||||
###########################################################################
|
||||
|
||||
# bug: it thinks that
|
||||
# http://cvs1.mozilla.org/webtools/tinderbox/data/knotts.gif
|
||||
# is 640x400, but it's really 200x245.
|
||||
# giftrans says of that image:
|
||||
#
|
||||
# Header: "GIF87a"
|
||||
# Logical Screen Descriptor:
|
||||
# Logical Screen Width: 640 pixels
|
||||
# Logical Screen Height: 480 pixels
|
||||
# Image Descriptor:
|
||||
# Image Width: 200 pixels
|
||||
# Image Height: 245 pixels
|
||||
|
||||
|
||||
sub gifsize {
|
||||
local($GIF) = @_;
|
||||
read($GIF, $type, 6);
|
||||
if(!($type =~ /GIF8[7,9]a/) ||
|
||||
!(read($GIF, $s, 4) == 4) ){
|
||||
Error "Invalid or Corrupted GIF";
|
||||
$size="";
|
||||
} else {
|
||||
($a,$b,$c,$d)=unpack("C"x4,$s);
|
||||
$size=join ("", 'WIDTH=', $b<<8|$a, ' HEIGHT=', $d<<8|$c);
|
||||
}
|
||||
return $size;
|
||||
}
|
||||
|
||||
sub xbmsize {
|
||||
local($XBM) = @_;
|
||||
local($input)="";
|
||||
|
||||
$input .= <$XBM>;
|
||||
$input .= <$XBM>;
|
||||
$_ = $input;
|
||||
if( /#define\s*\S*\s*\d*\s*\n#define\s*\S*\s*\d*\s*\n/i ){
|
||||
($a,$b)=/#define\s*\S*\s*(\d*)\s*\n#define\s*\S*\s*(\d*)\s*\n/i;
|
||||
$size=join ("", 'WIDTH=', $a, ' HEIGHT=', $b );
|
||||
} else {
|
||||
Error "Doesn't look like an XBM file";
|
||||
}
|
||||
return $size;
|
||||
}
|
||||
|
||||
# jpegsize : gets the width and height (in pixels) of a jpeg file
|
||||
# Andrew Tong, werdna@ugcs.caltech.edu February 14, 1995
|
||||
# modified slightly by alex@ed.ac.uk
|
||||
sub jpegsize {
|
||||
local($JPEG) = @_;
|
||||
local($done)=0;
|
||||
$size="";
|
||||
|
||||
read($JPEG, $c1, 1); read($JPEG, $c2, 1);
|
||||
if( !((ord($c1) == 0xFF) && (ord($c2) == 0xD8))){
|
||||
my $s = sprintf "This is not a JPEG! (Codes %02X %02X)\n", ord($c1), ord($c2);
|
||||
Error $s;
|
||||
$done=1;
|
||||
}
|
||||
while (ord($ch) != 0xDA && !$done) {
|
||||
# Find next marker (JPEG markers begin with 0xFF)
|
||||
# This can hang the program!!
|
||||
while (ord($ch) != 0xFF) { read($JPEG, $ch, 1); }
|
||||
# JPEG markers can be padded with unlimited 0xFF's
|
||||
while (ord($ch) == 0xFF) { read($JPEG, $ch, 1); }
|
||||
# Now, $ch contains the value of the marker.
|
||||
$marker=ord($ch);
|
||||
|
||||
if (($marker >= 0xC0) && ($marker <= 0xCF) &&
|
||||
($marker != 0xC4) && ($marker != 0xCC)) { # it's a SOFn marker
|
||||
read ($JPEG, $junk, 3); read($JPEG, $s, 4);
|
||||
($a,$b,$c,$d)=unpack("C"x4,$s);
|
||||
$size=join("", 'HEIGHT=',$a<<8|$b,' WIDTH=',$c<<8|$d );
|
||||
$done=1;
|
||||
} else {
|
||||
# We **MUST** skip variables, since FF's within variable
|
||||
# names are NOT valid JPEG markers
|
||||
read ($JPEG, $s, 2);
|
||||
($c1, $c2) = unpack("C"x2,$s);
|
||||
$length = $c1<<8|$c2;
|
||||
if( ($length < 2) ){
|
||||
Error "Bad JPEG file: erroneous marker length";
|
||||
$done=1;
|
||||
} else {
|
||||
read($JPEG, $junk, $length-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $size;
|
||||
}
|
||||
|
||||
###########################################################################
|
||||
# Subroutine grabs a gif from another server and gets its size
|
||||
###########################################################################
|
||||
|
||||
|
||||
sub URLsize {
|
||||
my ($fullurl) = @_;
|
||||
|
||||
$_ = $fullurl;
|
||||
if ( ! m@^http://@ ) {
|
||||
Error "HTTP URLs only, please: \"$_\" is no good.";
|
||||
}
|
||||
|
||||
my($dummy, $dummy, $serverstring, $url) = split(/\//, $fullurl, 4);
|
||||
my($them,$port) = split(/:/, $serverstring);
|
||||
my $port = 80 unless $port;
|
||||
my $size="";
|
||||
|
||||
$_ = $them;
|
||||
if ( m@^[^.]*$@ ) {
|
||||
Error "Fully-qualified host names only, please: \"$_\" is no good.";
|
||||
}
|
||||
|
||||
$_=$url;
|
||||
my ($remote, $iaddr, $paddr, $proto, $line);
|
||||
$remote = $them;
|
||||
if ($port =~ /\D/) { $port = getservbyname($port, 'tcp') }
|
||||
die "No port" unless $port;
|
||||
$iaddr = inet_aton($remote) || die "no host: $remote";
|
||||
$paddr = sockaddr_in($port, $iaddr);
|
||||
|
||||
$proto = getprotobyname('tcp');
|
||||
socket(S, PF_INET, SOCK_STREAM, $proto) || die "socket: $!";
|
||||
connect(S, $paddr) || die "connect: $!";
|
||||
select(S); $| = 1; select(STDOUT);
|
||||
|
||||
print S "GET /$url HTTP/1.0\r\n";
|
||||
print S "Host: $them\r\n";
|
||||
print S "User-Agent: Tinderbox/0.0\r\n";
|
||||
print S "\r\n";
|
||||
|
||||
$_ = <S>;
|
||||
if (! m@^HTTP/[0-9.]+ 200@ ) {
|
||||
Error "$them responded:<BR> $_";
|
||||
}
|
||||
|
||||
my $ctype = "";
|
||||
while (<S>) {
|
||||
# print "read: $_<br>\n";
|
||||
if ( m@^Content-Type:[ \t]*([^ \t\r\n]+)@io ) {
|
||||
$ctype = $1;
|
||||
}
|
||||
last if (/^[\r\n]/);
|
||||
}
|
||||
|
||||
$_ = $ctype;
|
||||
if ( $_ eq "" ) {
|
||||
Error "Server returned no content-type for \"$fullurl\"?";
|
||||
} elsif ( m@image/jpeg@i || m@image/pjpeg@i ) {
|
||||
$size = &jpegsize(S);
|
||||
} elsif ( m@image/gif@i ) {
|
||||
$size = &gifsize(S);
|
||||
} elsif ( m@image/xbm@i || m@image/x-xbm@i || m@image/x-xbitmap@i ) {
|
||||
$size = &xbmsize(S);
|
||||
} else {
|
||||
Error "Not a GIF, JPEG, or XBM: that was of type \"$ctype\".";
|
||||
}
|
||||
|
||||
$_ = $size;
|
||||
if( /\s*width\s*=\s*([0-9]*)\s*/i ){
|
||||
($newwidth)= /\s*width\s*=\s*(\d*)\s*/i;
|
||||
}
|
||||
if( /\s*height\s*=\s*([0-9]*)\s*/i ){
|
||||
($newheight)=/\s*height\s*=\s*(\d*)\s*/i;
|
||||
}
|
||||
|
||||
if ( $newwidth eq "" || $newheight eq "" ) {
|
||||
return "";
|
||||
} else {
|
||||
if ( $newwidth <= 5 || $newheight <= 5 ) {
|
||||
Error "${newwidth}x${newheight} seems small, don't you think?";
|
||||
} elsif ( $newwidth >= 400 || $newheight >= 400 ) {
|
||||
Error "${newwidth}x${newheight} is too big; please" .
|
||||
" keep it under 400x400."
|
||||
}
|
||||
return $size;
|
||||
}
|
||||
}
|
||||
|
||||
sub dokill {
|
||||
kill 9,$child if $child;
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
use lib "../bonsai";
|
||||
|
||||
require "globals.pl";
|
||||
require 'lloydcgi.pl';
|
||||
|
||||
$buildname = $form{'buildname'};
|
||||
$buildtime = $form{'buildtime'};
|
||||
$errorparser = $form{'errorparser'};
|
||||
$logfile = $form{'logfile'};
|
||||
$tree = $form{'tree'};
|
||||
$enc_buildname = &url_encode($buildname);
|
||||
$note = $form{'note'};
|
||||
$who = $form{'who'};
|
||||
$now = time;
|
||||
$now_str = &print_time($now);
|
||||
|
||||
$|=1;
|
||||
|
||||
print "Content-type: text/html\n\n<HTML>\n";
|
||||
|
||||
if( $url = $form{"note"} ){
|
||||
|
||||
$enc_note = url_encode( $note );
|
||||
lock;
|
||||
open( NOTES,">>$tree/notes.txt");
|
||||
print NOTES "$buildtime|$buildname|$who|$now|$enc_note\n";
|
||||
close(NOTES);
|
||||
|
||||
print "<H1>The following comment has been added to the log</h1>\n";
|
||||
|
||||
#print "$buildname \n $buildtime \n $errorparser \n $logfile \n $tree \n $enc_buildname \n";
|
||||
print "<pre>\n[<b>$who - $now_str</b>]\n$note\n</pre>";
|
||||
|
||||
print"
|
||||
<p><a href=\"showlog.cgi?tree=$tree\&buildname=$enc_buildname\&buildtime=$buildtime\&logfile=$logfile\&errorparser=$errorparser\">
|
||||
Go back to the Error Log</a>
|
||||
<a href=\"showbuilds.cgi?tree=$tree\">
|
||||
<br>Go back to the build Page</a>
|
||||
";
|
||||
|
||||
}
|
||||
else {
|
||||
if( $buildname eq '' || $buildtime == 0 ){
|
||||
print "<h1>Invalid parameters</h1>\n";
|
||||
die "\n";
|
||||
}
|
||||
|
||||
#print "$buildname \n $buildtime \n $errorparser \n $logfile \n $tree \n $enc_buildname \n";
|
||||
|
||||
print "
|
||||
<title>Add a Comment to the log</title>
|
||||
<H1>Add a Comment to the log</h1>
|
||||
|
||||
<form action='addnote.cgi' METHOD='post'>
|
||||
|
||||
<br>Your email address: <INPUT Type='input' name='who' size=10>
|
||||
<TEXTAREA NAME=note ROWS=10 COLS=70>
|
||||
</textarea>
|
||||
<INPUT Type='hidden' name='buildname' value='${buildname}'>
|
||||
<INPUT Type='hidden' name='buildtime' value='${buildtime}'>
|
||||
<INPUT Type='hidden' name='errorparser' value='$errorparser'>
|
||||
<INPUT Type='hidden' name='logfile' value='$logfile'>
|
||||
<INPUT Type='hidden' name='tree' value='$tree'>
|
||||
<INPUT Type='submit' name='submit' value='Add Note To Log'>
|
||||
</form>
|
||||
";
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
use lib "../bonsai";
|
||||
|
||||
require 'lloydcgi.pl';
|
||||
require 'globals.pl';
|
||||
require 'header.pl';
|
||||
|
||||
$|=1;
|
||||
|
||||
print "Content-type: text/html\n\n<HTML>\n";
|
||||
|
||||
EmitHtmlHeader("administer tinderbox", "tree: $tree");
|
||||
|
||||
&load_data;
|
||||
|
||||
|
||||
if( -r "$tree/mod.pl" ){
|
||||
require "$tree/mod.pl";
|
||||
}
|
||||
else {
|
||||
$message_of_day = "";
|
||||
}
|
||||
|
||||
print "
|
||||
<FORM method=post action=doadmin.cgi>
|
||||
<B>Password:</B> <INPUT NAME=password TYPE=password>
|
||||
<INPUT TYPE=HIDDEN NAME=tree VALUE=$tree>
|
||||
<INPUT TYPE=HIDDEN NAME=command VALUE=set_message>
|
||||
<br><b>Message of the Day
|
||||
<br><TEXTAREA NAME=message ROWS=10 COLS=70>$message_of_day
|
||||
</TEXTAREA>
|
||||
<br><INPUT TYPE=SUBMIT VALUE='Set Message of the Day'>
|
||||
</FORM>
|
||||
<hr>
|
||||
";
|
||||
|
||||
|
||||
print "
|
||||
<FORM method=post action=doadmin.cgi>
|
||||
<B>Password:</B> <INPUT NAME=password TYPE=password>
|
||||
<INPUT TYPE=HIDDEN NAME=tree VALUE=$tree>
|
||||
<INPUT TYPE=HIDDEN NAME=command VALUE=trim_logs>
|
||||
<br><b>Trim Logs to <INPUT NAME=days size=5 VALUE='7'> days.</b> (Tinderbox
|
||||
shows 2 days history by default. You can see more by clicking show all).
|
||||
<br><INPUT TYPE=SUBMIT VALUE='Trim Logs'>
|
||||
</FORM>
|
||||
<FORM method=post action=doadmin.cgi>
|
||||
<hr>
|
||||
" ;
|
||||
|
||||
|
||||
print "
|
||||
<FORM method=post action=doadmin.cgi>
|
||||
<B>Password:</B> <INPUT NAME=password TYPE=password> <BR>
|
||||
<INPUT TYPE=HIDDEN NAME=tree VALUE=$tree>
|
||||
<INPUT TYPE=HIDDEN NAME=command VALUE=create_tree>
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TD><B>tinderbox tree name:</B></TD>
|
||||
<TD><INPUT NAME=treename VALUE=''></TD>
|
||||
</TR><TR>
|
||||
<TD><B>cvs module name:</B></TD>
|
||||
<TD><INPUT NAME=modulename VALUE=''></TD>
|
||||
</TR><TR>
|
||||
<TD><B>cvs branch:</B></TD>
|
||||
<TD><INPUT NAME=branchname VALUE='HEAD'></TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
<INPUT TYPE=SUBMIT VALUE='Create a new Tinderbox page'>
|
||||
</FORM>
|
||||
<FORM method=post action=doadmin.cgi>
|
||||
<hr>
|
||||
|
||||
<B>Password:</B> <INPUT NAME=password TYPE=password> <BR>
|
||||
<INPUT TYPE=HIDDEN NAME=tree VALUE=$tree>
|
||||
<INPUT TYPE=HIDDEN NAME=command VALUE=remove_build>
|
||||
";
|
||||
|
||||
$i = 1;
|
||||
while( $i <= $name_count ){
|
||||
$n = $build_name_names->[$i];
|
||||
print "<INPUT TYPE=radio NAME=build VALUE='$n'>";
|
||||
print "$n<br>\n";
|
||||
$i++;
|
||||
}
|
||||
|
||||
print "
|
||||
<INPUT TYPE=SUBMIT VALUE='Remove Build From Page'>
|
||||
</FORM>
|
||||
<hr>
|
||||
";
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
use lib "../bonsai";
|
||||
|
||||
require 'globals.pl';
|
||||
|
||||
$F_DEBUG=1;
|
||||
|
||||
|
||||
$tree = $ARGV[0];
|
||||
|
||||
open(SEMFILE, ">>$tree/buildwho.sem") || die "Couldn't open semaphore file!";
|
||||
if (!flock(SEMFILE, 2 + 4)) { # 2 means "lock"; 4 means "fail immediately if
|
||||
# lock already taken".
|
||||
print "buildwho.pl: Another process is currently building the database.\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
require "$tree/treedata.pl";
|
||||
|
||||
if( $cvs_root eq '' ){
|
||||
$CVS_ROOT = '/m/src';
|
||||
}
|
||||
else {
|
||||
$CVS_ROOT = $cvs_root;
|
||||
}
|
||||
|
||||
$CVS_REPOS_SUFIX = $CVS_ROOT;
|
||||
$CVS_REPOS_SUFIX =~ s/\//_/g;
|
||||
|
||||
$CHECKIN_DATA_FILE = "/d/webdocs/projects/bonsai/data/checkinlog${CVS_REPOS_SUFIX}";
|
||||
$CHECKIN_INDEX_FILE = "/d/webdocs/projects/bonsai/data/index${CVS_REPOS_SUFIX}";
|
||||
|
||||
require 'cvsquery.pl';
|
||||
|
||||
print "cvsroot='$CVS_ROOT'\n";
|
||||
|
||||
&build_who;
|
||||
|
||||
flock(SEMFILE, 8); # '8' is magic 'unlock' const.
|
||||
close SEMFILE;
|
||||
|
||||
|
||||
sub build_who {
|
||||
open(BUILDLOG, "<$tree/build.dat" );
|
||||
$line = <BUILDLOG>;
|
||||
close(BUILDLOG);
|
||||
|
||||
#($j,$query_date_min) = split(/\|/, $line);
|
||||
$query_date_min = time - (60 * 60 * 40);
|
||||
|
||||
if( $F_DEBUG ){
|
||||
print "Minimum date: $query_date_min\n";
|
||||
}
|
||||
|
||||
$query_module=$cvs_module;
|
||||
$query_branch=$cvs_branch;
|
||||
|
||||
$result = &query_checkins;
|
||||
|
||||
|
||||
$last_who='';
|
||||
$last_date=0;
|
||||
open(WHOLOG, ">$tree/who.dat" );
|
||||
for $ci (@$result) {
|
||||
if( $ci->[$CI_DATE] != $last_date || $ci->[$CI_WHO] != $last_who ){
|
||||
print WHOLOG "$ci->[$CI_DATE]|$ci->[$CI_WHO]\n";
|
||||
}
|
||||
$last_who=$ci->[$CI_WHO];
|
||||
$last_date=$ci->[$CI_DATE];
|
||||
}
|
||||
close( WHOLOG );
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
chdir '/d/webdocs/projects/tinderbox';
|
||||
|
||||
#print "cd ok\n";
|
||||
|
||||
open FL, "find . -name \"*.gz\" -mtime +7 -print |";
|
||||
|
||||
#print "find ok\n";
|
||||
|
||||
while( <FL> ){
|
||||
chop();
|
||||
#print "unlink $_\n";
|
||||
unlink $_;
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
#!/tools/ns/bin/perl5
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
#
|
||||
# to run this script execute 'nohup copydata.pl &' from the tinderbox directory
|
||||
#
|
||||
|
||||
$start_dir = `pwd`;
|
||||
chop($start_dir);
|
||||
$scp_cmd = "scp -o 'User snapshot' -o'Port 22' -o 'UserKnownHostsFile /u/shaver/snapshot/known_hosts' -o 'IdentityFile /u/shaver/snapshot/identity'";
|
||||
|
||||
|
||||
$last_time = 0;
|
||||
|
||||
$min_cycle_time = 3 * 60; # 3 minutes
|
||||
|
||||
print "starting dir is :$start_dir\n";
|
||||
|
||||
while( 1 ){
|
||||
chdir("$start_dir");
|
||||
if( time - $last_time < $min_cycle_time ){
|
||||
$sleep_time = $min_cycle_time - (time - $last_time);
|
||||
print "\n\nSleeping $sleep_time seconds ...\n";
|
||||
sleep( $sleep_time );
|
||||
}
|
||||
|
||||
©_data("Mozilla");
|
||||
©_data("raptor");
|
||||
|
||||
chdir( "$start_dir");
|
||||
print "$scp_cmd * cvs1.mozilla.org:/e/webtools/tinderbox\n";
|
||||
system "$scp_cmd * cvs1.mozilla.org:/e/webtools/tinderbox";
|
||||
|
||||
chdir( "$start_dir/../bonsai");
|
||||
print "$scp_cmd * cvs1.mozilla.org:/e/webtools/bonsai\n";
|
||||
system "$scp_cmd * cvs1.mozilla.org:/e/webtools/bonsai";
|
||||
|
||||
|
||||
$last_time = time;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
|
||||
sub copy_data {
|
||||
local($data_dir) = @_;
|
||||
local($zips,$qry);
|
||||
|
||||
chdir $data_dir || die "couldn't chdir to $data_dir";
|
||||
|
||||
system "echo hello >lastup.new";
|
||||
|
||||
if( -r 'lastup' ) {
|
||||
$qry = '-newer lastup.old';
|
||||
rename 'lastup', 'lastup.old'
|
||||
}
|
||||
rename 'lastup.new', 'lastup';
|
||||
|
||||
|
||||
open( FINDER, "find . $qry -name \"*.gz\" -print|" );
|
||||
while(<FINDER>){
|
||||
print;
|
||||
chop;
|
||||
$zips .= "$_ ";
|
||||
}
|
||||
close( FINDER );
|
||||
|
||||
unlink 'lastup.old';
|
||||
|
||||
print "$scp_cmd *.txt $zips *.dat cvs1.mozilla.org:/e/webtools/tinderbox/$data_dir\n";
|
||||
system "$scp_cmd *.txt $zips *.dat cvs1.mozilla.org:/e/webtools/tinderbox/$data_dir";
|
||||
|
||||
|
||||
chdir $start_dir || die "couldn't chdir to $start_dir";
|
||||
}
|
|
@ -0,0 +1,174 @@
|
|||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
|
||||
use lib "../bonsai";
|
||||
require 'lloydcgi.pl';
|
||||
require 'globals.pl';
|
||||
|
||||
umask O666;
|
||||
|
||||
$|=1;
|
||||
|
||||
check_password();
|
||||
|
||||
print "Content-type: text/html\n\n<HTML>\n";
|
||||
|
||||
$command = $form{'command'};
|
||||
$tree= $form{'tree'};
|
||||
|
||||
if( $command eq 'create_tree' ){
|
||||
&create_tree;
|
||||
}
|
||||
elsif( $command eq 'remove_build' ){
|
||||
&remove_build;
|
||||
}
|
||||
elsif( $command eq 'trim_logs' ){
|
||||
&trim_logs;
|
||||
}
|
||||
elsif( $command eq 'set_message' ){
|
||||
&set_message;
|
||||
} else {
|
||||
print "Unknown command: \"$command\".";
|
||||
}
|
||||
|
||||
sub trim_logs {
|
||||
$days = $form{'days'};
|
||||
$tree = $form{'tree'};
|
||||
|
||||
print "<h2>Trimming Log files for $tree...</h2>\n<p>";
|
||||
|
||||
$min_date = time - (60*60*24 * $days);
|
||||
|
||||
#
|
||||
# Nuke the old log files
|
||||
#
|
||||
$i = 0;
|
||||
opendir( D, 'DogbertTip' );
|
||||
while( $fn = readdir( D ) ){
|
||||
if( $fn =~ /\.gz$/ ){
|
||||
($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,
|
||||
$ctime,$blksize,$blocks) = stat("$tree/$fn");
|
||||
if( $mtime && ($mtime < $min_date) ){
|
||||
print "$fn\n";
|
||||
$tblocks += $blocks;
|
||||
unlink( "$tree/$fn" );
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir( D );
|
||||
$k = $tblocks*512/1024;
|
||||
print "<br><b>$i Logfiles ( $k K bytes ) removed</b><br>\n";
|
||||
|
||||
#
|
||||
# Trim build.dat
|
||||
#
|
||||
$builds_removed = 0;
|
||||
open(BD, "<$tree/build.dat");
|
||||
open(NBD, ">$tree/build.dat.new");
|
||||
while( <BD> ){
|
||||
($mailtime,$buildtime,$buildname) = split( /\|/ );
|
||||
if( $buildtime >= $min_date ){
|
||||
print NBD $_;
|
||||
}
|
||||
else {
|
||||
$builds_removed++;
|
||||
}
|
||||
}
|
||||
close( BD );
|
||||
close( NBD );
|
||||
|
||||
rename( "$tree/build.dat", "$tree/build.dat.old" );
|
||||
rename( "$tree/build.dat.new", "$tree/build.dat" );
|
||||
|
||||
print "<h2>$builds_removed Builds removed from build.dat</h2>\n";
|
||||
}
|
||||
|
||||
sub create_tree {
|
||||
$treename = $form{'treename'};
|
||||
$modulename = $form{'modulename'};
|
||||
$branchname = $form{'branchname'};
|
||||
|
||||
if( -r $treename ){
|
||||
chmod 0777, $treename;
|
||||
}
|
||||
else {
|
||||
mkdir( $treename, 0777 ) || die "<h1> Cannot mkdir $treename</h1>";
|
||||
}
|
||||
open( F, ">$treename/treedata.pl" );
|
||||
print F "\$cvs_module='$modulename';\n";
|
||||
print F "\$cvs_branch='$branchname';\n";
|
||||
close( F );
|
||||
|
||||
open( F, ">$treename/build.dat" );
|
||||
close( F );
|
||||
|
||||
open( F, ">$treename/who.dat" );
|
||||
close( F );
|
||||
|
||||
open( F, ">$treename/notes.txt" );
|
||||
close( F );
|
||||
|
||||
chmod 0777, "$treename/build.dat", "$treename/who.dat", "$treename/notes.txt",
|
||||
"$treename/treedata.pl";
|
||||
|
||||
print "<h2><a href=showbuilds.cgi?tree=$treename>Tree created or modified</a></h2>\n";
|
||||
}
|
||||
|
||||
sub remove_build {
|
||||
$build_name = $form{'build'};
|
||||
|
||||
#
|
||||
# Trim build.dat
|
||||
#
|
||||
$builds_removed = 0;
|
||||
open(BD, "<$tree/build.dat");
|
||||
open(NBD, ">$tree/build.dat.new");
|
||||
while( <BD> ){
|
||||
($mailtime,$buildtime,$bname) = split( /\|/ );
|
||||
if( $bname ne $build_name ){
|
||||
print NBD $_;
|
||||
}
|
||||
else {
|
||||
$builds_removed++;
|
||||
}
|
||||
}
|
||||
close( BD );
|
||||
close( NBD );
|
||||
chmod( 0777, "$tree/build.dat.new");
|
||||
|
||||
rename( "$tree/build.dat", "$tree/build.dat.old" );
|
||||
rename( "$tree/build.dat.new", "$tree/build.dat" );
|
||||
|
||||
print "<h2><a href=showbuilds.cgi?tree=$tree>
|
||||
$builds_removed Builds removed from build.dat</a></h2>\n";
|
||||
}
|
||||
|
||||
sub set_message {
|
||||
$m = $form{'message'};
|
||||
$m =~ s/\"/\\\"/g;
|
||||
open(MOD, ">$tree/mod.pl");
|
||||
print MOD "\$message_of_day = \"$m\"";
|
||||
close(MOD);
|
||||
chmod( 0777, "$tree/mod.pl");
|
||||
print "<h2><a href=showbuilds.cgi?tree=$tree>
|
||||
Message Changed</a></h2>\n";
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
1;
|
||||
#
|
||||
# Scan a line and see if it has an error
|
||||
#
|
||||
sub has_error {
|
||||
$line =~ /fatal error/ # link error
|
||||
|| $line =~ /Error / # C error
|
||||
|| $line =~ /\[checkout aborted\]/ #cvs error
|
||||
;
|
||||
}
|
||||
|
||||
sub has_warning {
|
||||
$line =~ /^[A-Za-z0-9_]+\.[A-Za-z0-9]+\ line [0-9]+/ ;
|
||||
}
|
||||
|
||||
sub has_errorline {
|
||||
local( $line ) = @_;
|
||||
if( $line =~ /^(([A-Za-z0-9_]+\.[A-Za-z0-9]+) line ([0-9]+))/ ){
|
||||
$error_file = $1;
|
||||
$error_file_ref = $2;
|
||||
$error_line = $3;
|
||||
$error_guess = 1;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
1;
|
||||
#
|
||||
# Scan a line and see if it has an error
|
||||
#
|
||||
sub has_error {
|
||||
$line =~ /fatal error/ # link error
|
||||
|| $line =~ /^C / # cvs merge conflict
|
||||
|| $line =~ / Error: / # C error
|
||||
|| $line =~ / error\([0-9]*\)\:/ # C error
|
||||
|| ($line =~ /gmake/ && $line =~ / Error /)
|
||||
|| $line =~ /\[checkout aborted\]/ #cvs error
|
||||
|| $line =~ /\: cannot find module/ #cvs error
|
||||
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
sub has_warning {
|
||||
$line =~ /^[A-Za-z0-9_]+\.[A-Za-z0-9]+\:[0-9]+\:/
|
||||
|| $line =~ /^\"[A-Za-z0-9_]+\.[A-Za-z0-9]+\"\, line [0-9]+\:/
|
||||
;
|
||||
}
|
||||
|
||||
sub has_errorline {
|
||||
local( $line ) = @_;
|
||||
if( $line =~ /^(([A-Za-z0-9_]+\.[A-Za-z0-9]+)\:([0-9]+)\:)/ ){
|
||||
$error_file = $1;
|
||||
$error_file_ref = $2;
|
||||
$error_line = $3;
|
||||
$error_guess = 1;
|
||||
return 1;
|
||||
}
|
||||
if ( $line =~ /^(\"([A-Za-z0-9_]+\.[A-Za-z0-9]+)\"\, line ([0-9]+)\:)/ ){
|
||||
$error_file = $1;
|
||||
$error_file_ref = $2;
|
||||
$error_line = $3;
|
||||
$error_guess = 1;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
1;
|
||||
#
|
||||
# Scan a line and see if it has an error
|
||||
#
|
||||
sub has_error {
|
||||
$line =~ /fatal error/ # link error
|
||||
|| $line =~ / error / # C error
|
||||
|| $line =~ /^C / # cvs merge conflict
|
||||
|| $line =~ /error C/ # C error
|
||||
|| $line =~ /Creating new precompiled header/ # Wastes time.
|
||||
|| $line =~ /error:/ # java error
|
||||
|| $line =~ /jmake.MakerFailedException:/ # java error
|
||||
|| $line =~ /Unknown host / # cvs error
|
||||
|| $line =~ /: build failed\;/ # nmake error
|
||||
|| ($line =~ /gmake/ && $line =~ / Error /)
|
||||
|| $line =~ /\[checkout aborted\]/ #cvs error
|
||||
|| $line =~ /\: cannot find module/ #cvs error
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
sub has_warning {
|
||||
$line =~ /: warning/ # link error
|
||||
|| $line =~ / error / # C error
|
||||
;
|
||||
}
|
||||
|
||||
sub has_errorline {
|
||||
local( $line ) = @_;
|
||||
$error_file = ''; #'NS\CMD\WINFE\CXICON.cpp';
|
||||
$error_line = 0;
|
||||
|
||||
if( $line =~ m@(ns([\\/][a-z0-9\._]+)*)@i ){
|
||||
$error_file = $1;
|
||||
$error_file_ref = lc $error_file;
|
||||
$error_file_ref =~ s@\\@/@g;
|
||||
|
||||
$line =~ m/\(([0-9]+)\)/;
|
||||
$error_line = $1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if( $line =~ m@(^([A-Za-z0-9_]+\.[A-Za-z])+\(([0-9]+)\))@ ){
|
||||
$error_file = $1;
|
||||
$error_file_ref = lc $2;
|
||||
$error_line = $3;
|
||||
$error_guess=1;
|
||||
$error_file_ref =~ s@\\@/@g;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
|
||||
<META NAME="GENERATOR" CONTENT="Mozilla/4.0b2 (WinNT; I) [Netscape]">
|
||||
</HEAD>
|
||||
<BODY>
|
||||
|
||||
<H1>
|
||||
FAQ on Tinderbox </H1>
|
||||
<B><FONT SIZE=+2>Q. What is Tinderbox.</FONT></B>
|
||||
<BR><FONT SIZE=+2>A. Your very own automated build page. It shows you how builds
|
||||
are going on various platforms. fs</FONT>
|
||||
<BR><FONT SIZE=+2></FONT>
|
||||
<BR><B><FONT SIZE=+2>Q. I just checked in some code. How can I tell when
|
||||
I'm OK.</FONT></B>
|
||||
<BR><FONT SIZE=+2>A. You name will appear in the <I>guilty </I>column.
|
||||
When there are successful (<FONT COLOR="#00FF00">green</FONT>) builds in
|
||||
all the columns in a row <B>above</B> your name, you know you are ok.</FONT>
|
||||
<BR>
|
||||
<BR><B><FONT SIZE=+2>Q. The tree is broken, how do I find out what is busted
|
||||
(or who busted it).</FONT></B>
|
||||
<BR><FONT SIZE=+2>A. Clicking 'L' in the first red box (first build to break)
|
||||
above a green will show you a build log for the broken build. You
|
||||
can also click 'C' in this box and see what code was checked in.</FONT>
|
||||
<BR>
|
||||
<BR><B><FONT SIZE=+2>More Questions? Mail me <A HREF="mailto:ltabb@netscape.com">ltabb@netscape.com</A></FONT></B>
|
||||
<BR>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
|
@ -0,0 +1,217 @@
|
|||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
use Socket;
|
||||
|
||||
require 'globals.pl';
|
||||
require 'imagelog.pl';
|
||||
|
||||
# Port an old-style imagelog thing to a newstyle one
|
||||
|
||||
open( IMAGELOG, "<$data_dir/imagelog.txt" ) || die "can't open file";
|
||||
open (OUT, ">$data_dir/newimagelog.txt") || die "can't open output file";
|
||||
select(OUT); $| = 1; select(STDOUT);
|
||||
|
||||
while( <IMAGELOG> ){
|
||||
chop;
|
||||
($url,$quote) = split(/\`/);
|
||||
print "$url\n";
|
||||
$size = &URLsize($url);
|
||||
$width = "";
|
||||
$height = "";
|
||||
if ($size =~ /WIDTH=([0-9]*)/) {
|
||||
$width = $1;
|
||||
}
|
||||
if ($size =~ /HEIGHT=([0-9]*)/) {
|
||||
$height = $1;
|
||||
}
|
||||
if ($width eq "" || $height eq "") {
|
||||
print "Couldn't get image size; skipping.\n";
|
||||
} else {
|
||||
print OUT "$url`$width`$height`$quote\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
sub imgsize {
|
||||
local($file)= @_;
|
||||
|
||||
#first try to open the file
|
||||
if( !open(STREAM, "<$file") ){
|
||||
print "Can't open IMG $file";
|
||||
$size="";
|
||||
} else {
|
||||
if ($file =~ /.jpg/i || $file =~ /.jpeg/i) {
|
||||
$size = &jpegsize(STREAM);
|
||||
} elsif($file =~ /.gif/i) {
|
||||
$size = &gifsize(STREAM);
|
||||
} elsif($file =~ /.xbm/i) {
|
||||
$size = &xbmsize(STREAM);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
$_ = $size;
|
||||
if( /\s*width\s*=\s*([0-9]*)\s*/i ){
|
||||
($newwidth)= /\s*width\s*=\s*(\d*)\s*/i;
|
||||
}
|
||||
if( /\s*height\s*=\s*([0-9]*)\s*/i ){
|
||||
($newheight)=/\s*height\s*=\s*(\d*)\s*/i;
|
||||
}
|
||||
close(STREAM);
|
||||
}
|
||||
return $size;
|
||||
}
|
||||
|
||||
###########################################################################
|
||||
# Subroutine gets the size of the specified GIF
|
||||
###########################################################################
|
||||
sub gifsize {
|
||||
local($GIF) = @_;
|
||||
read($GIF, $type, 6);
|
||||
if(!($type =~ /GIF8[7,9]a/) ||
|
||||
!(read($GIF, $s, 4) == 4) ){
|
||||
print "Invalid or Corrupted GIF";
|
||||
$size="";
|
||||
} else {
|
||||
($a,$b,$c,$d)=unpack("C"x4,$s);
|
||||
$size=join ("", 'WIDTH=', $b<<8|$a, ' HEIGHT=', $d<<8|$c);
|
||||
}
|
||||
return $size;
|
||||
}
|
||||
|
||||
sub xbmsize {
|
||||
local($XBM) = @_;
|
||||
local($input)="";
|
||||
|
||||
$input .= <$XBM>;
|
||||
$input .= <$XBM>;
|
||||
$_ = $input;
|
||||
if( /#define\s*\S*\s*\d*\s*\n#define\s*\S*\s*\d*\s*\n/i ){
|
||||
($a,$b)=/#define\s*\S*\s*(\d*)\s*\n#define\s*\S*\s*(\d*)\s*\n/i;
|
||||
$size=join ("", 'WIDTH=', $a, ' HEIGHT=', $b );
|
||||
} else {
|
||||
print "Hmmm... Doesn't look like an XBM file";
|
||||
}
|
||||
return $size;
|
||||
}
|
||||
|
||||
# jpegsize : gets the width and height (in pixels) of a jpeg file
|
||||
# Andrew Tong, werdna@ugcs.caltech.edu February 14, 1995
|
||||
# modified slightly by alex@ed.ac.uk
|
||||
sub jpegsize {
|
||||
local($JPEG) = @_;
|
||||
local($done)=0;
|
||||
$size="";
|
||||
|
||||
read($JPEG, $c1, 1); read($JPEG, $c2, 1);
|
||||
if( !((ord($c1) == 0xFF) && (ord($c2) == 0xD8))){
|
||||
printf "This is not a JPEG! (Codes %02X %02X)\n", ord($c1), ord($c2);
|
||||
$done=1;
|
||||
}
|
||||
while (ord($ch) != 0xDA && !$done) {
|
||||
# Find next marker (JPEG markers begin with 0xFF)
|
||||
# This can hang the program!!
|
||||
while (ord($ch) != 0xFF) { read($JPEG, $ch, 1); }
|
||||
# JPEG markers can be padded with unlimited 0xFF's
|
||||
while (ord($ch) == 0xFF) { read($JPEG, $ch, 1); }
|
||||
# Now, $ch contains the value of the marker.
|
||||
$marker=ord($ch);
|
||||
|
||||
if (($marker >= 0xC0) && ($marker <= 0xCF) &&
|
||||
($marker != 0xC4) && ($marker != 0xCC)) { # it's a SOFn marker
|
||||
read ($JPEG, $junk, 3); read($JPEG, $s, 4);
|
||||
($a,$b,$c,$d)=unpack("C"x4,$s);
|
||||
$size=join("", 'HEIGHT=',$a<<8|$b,' WIDTH=',$c<<8|$d );
|
||||
$done=1;
|
||||
} else {
|
||||
# We **MUST** skip variables, since FF's within variable
|
||||
# names are NOT valid JPEG markers
|
||||
read ($JPEG, $s, 2);
|
||||
($c1, $c2) = unpack("C"x2,$s);
|
||||
$length = $c1<<8|$c2;
|
||||
if( ($length < 2) ){
|
||||
print "Erroneous JPEG marker length";
|
||||
$done=1;
|
||||
} else {
|
||||
read($JPEG, $junk, $length-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $size;
|
||||
}
|
||||
|
||||
###########################################################################
|
||||
# Subroutine grabs a gif from another server and gets its size
|
||||
###########################################################################
|
||||
|
||||
|
||||
sub URLsize {
|
||||
my ($fullurl) = @_;
|
||||
my($dummy, $dummy, $serverstring, $url) = split(/\//, $fullurl, 4);
|
||||
my($them,$port) = split(/:/, $serverstring);
|
||||
my $port = 80 unless $port;
|
||||
$them = 'localhost' unless $them;
|
||||
my $size="";
|
||||
|
||||
$_=$url;
|
||||
if( /gif/i || /jpeg/i || /jpg/i || /xbm/i ) {
|
||||
my ($remote, $iaddr, $paddr, $proto, $line);
|
||||
$remote = $them;
|
||||
if ($port =~ /\D/) { $port = getservbyname($port, 'tcp') }
|
||||
die "No port" unless $port;
|
||||
$iaddr = inet_aton($remote) || die "no host: $remote";
|
||||
$paddr = sockaddr_in($port, $iaddr);
|
||||
|
||||
$proto = getprotobyname('tcp');
|
||||
socket(S, PF_INET, SOCK_STREAM, $proto) || return "socket: $!";
|
||||
connect(S, $paddr) || return "connect: $!";
|
||||
select(S); $| = 1; select(STDOUT);
|
||||
|
||||
|
||||
|
||||
print S "GET /$url\n";
|
||||
if ($url =~ /.jpg/i || $url =~ /.jpeg/i) {
|
||||
$size = &jpegsize(S);
|
||||
} elsif($url =~ /.gif/i) {
|
||||
$size = &gifsize(S);
|
||||
} elsif($url =~ /.xbm/i) {
|
||||
$size = &xbmsize(S);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
$_ = $size;
|
||||
if( /\s*width\s*=\s*([0-9]*)\s*/i ){
|
||||
($newwidth)= /\s*width\s*=\s*(\d*)\s*/i;
|
||||
}
|
||||
if( /\s*height\s*=\s*([0-9]*)\s*/i ){
|
||||
($newheight)=/\s*height\s*=\s*(\d*)\s*/i;
|
||||
}
|
||||
} else {
|
||||
$size="";
|
||||
}
|
||||
return $size;
|
||||
}
|
||||
|
||||
sub dokill {
|
||||
kill 9,$child if $child;
|
||||
}
|
|
@ -0,0 +1,488 @@
|
|||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
#
|
||||
# Global variabls and functions for tinderbox
|
||||
#
|
||||
|
||||
#
|
||||
# Global variables
|
||||
#
|
||||
|
||||
$td1 = {};
|
||||
$td2 = {};
|
||||
|
||||
$build_list = []; # array of all build records
|
||||
$build_name_index = {};
|
||||
$build_name_names = [];
|
||||
$name_count = 0;
|
||||
|
||||
$build_time_index = {};
|
||||
$build_time_times = [];
|
||||
$time_count = 0;
|
||||
|
||||
$build_table = [];
|
||||
$who_list = [];
|
||||
$who_list2 = [];
|
||||
@note_array = ();
|
||||
|
||||
|
||||
#$body_tag = "<BODY TEXT=#000000 BGCOLOR=#8080C0 LINK=#FFFFFF VLINK=#800080 ALINK=#FFFF00>";
|
||||
#$body_tag = "<BODY TEXT=#000000 BGCOLOR=#FFFFC0 LINK=#0000FF VLINK=#800080 ALINK=#FF00FF>";
|
||||
if( $ENV{'USERNAME'} eq 'ltabb' ){
|
||||
$gzip = 'gzip';
|
||||
}
|
||||
else {
|
||||
$gzip = '/usr/local/bin/gzip';
|
||||
}
|
||||
|
||||
$data_dir='data';
|
||||
|
||||
$lock_count = 0;
|
||||
|
||||
1;
|
||||
|
||||
sub lock{
|
||||
#if( $lock_count == 0 ){
|
||||
# print "locking $tree/LOCKFILE.lck\n";
|
||||
# open( LOCKFILE_LOCK, ">$tree/LOCKFILE.lck" );
|
||||
# flock( LOCKFILE_LOCK, 2 );
|
||||
#}
|
||||
#$lock_count++;
|
||||
|
||||
}
|
||||
|
||||
sub unlock{
|
||||
#$lock_count--;
|
||||
#if( $lock_count == 0 ){
|
||||
# flock( LOCKFILE_LOCK, 8 );
|
||||
# close( LOCKFILE_LOCK );
|
||||
#}
|
||||
}
|
||||
|
||||
sub print_time {
|
||||
local($t) = @_;
|
||||
local($sec,$minute,$hour,$mday,$mon,$year);
|
||||
($sec,$minute,$hour,$mday,$mon,$year) = localtime( $t );
|
||||
sprintf("%02d/%02d %02d:%02d",$mon+1,$mday,$hour,$minute);
|
||||
}
|
||||
|
||||
sub url_encode {
|
||||
local( $s ) = @_;
|
||||
|
||||
$s =~ s/\%/\%25/g;
|
||||
$s =~ s/\=/\%3d/g;
|
||||
$s =~ s/\?/\%3f/g;
|
||||
$s =~ s/ /\%20/g;
|
||||
$s =~ s/\n/\%0a/g;
|
||||
$s =~ s/\r//g;
|
||||
$s =~ s/\"/\%22/g;
|
||||
$s =~ s/\'/\%27/g;
|
||||
$s =~ s/\|/\%7c/g;
|
||||
$s =~ s/\&/\%26/g;
|
||||
return $s;
|
||||
}
|
||||
|
||||
sub url_decode {
|
||||
local($value) = @_;
|
||||
$value =~ tr/+/ /;
|
||||
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
|
||||
return $value;
|
||||
}
|
||||
|
||||
|
||||
sub value_encode {
|
||||
my($s) = @_;
|
||||
$s =~ s@&@&@g;
|
||||
$s =~ s@<@<@g;
|
||||
$s =~ s@>@>@g;
|
||||
$s =~ s@\"@"@g;
|
||||
return $s;
|
||||
}
|
||||
|
||||
|
||||
sub load_data {
|
||||
$tree2 = $form{'tree2'};
|
||||
if( $tree2 ne '' ){
|
||||
require "$tree2/treedata.pl";
|
||||
$td2 = {};
|
||||
$td2->{name} = $tree2;
|
||||
$td2->{cvs_module} = $cvs_module;
|
||||
$td2->{cvs_branch} = $cvs_branch;
|
||||
$td2->{num} = 1;
|
||||
if( $cvs_root eq '' ){
|
||||
$cvs_root = '/m/src';
|
||||
}
|
||||
$td2->{cvs_root} = $cvs_root;
|
||||
|
||||
$tree = $form{'tree'};
|
||||
require "$tree/treedata.pl";
|
||||
if( $cvs_root eq '' ){
|
||||
$cvs_root = '/m/src';
|
||||
}
|
||||
}
|
||||
|
||||
$tree = $form{'tree'};
|
||||
|
||||
die "the \"tree\" parameter must be provided\n" unless $tree;
|
||||
|
||||
require "$tree/treedata.pl";
|
||||
$td1 = {};
|
||||
$td1->{name} = $tree;
|
||||
$td1->{num} = 0;
|
||||
$td1->{cvs_module} = $cvs_module;
|
||||
$td1->{cvs_branch} = $cvs_branch;
|
||||
if( $cvs_root eq '' ){
|
||||
$cvs_root = '/m/src';
|
||||
}
|
||||
$td1->{cvs_root} = $cvs_root;
|
||||
|
||||
&lock;
|
||||
&load_buildlog;
|
||||
&unlock;
|
||||
|
||||
&get_build_name_index;
|
||||
&get_build_time_index;
|
||||
|
||||
&load_who($who_list, $td1);
|
||||
if( $tree2 ne "" ){
|
||||
&load_who($who_list2, $td2);
|
||||
}
|
||||
|
||||
&make_build_table;
|
||||
}
|
||||
|
||||
sub load_buildlog {
|
||||
local($mailtime, $buildtime, $buildname, $errorparser, $buildstatus, $logfile,$binaryname);
|
||||
local($buildrec, @treelist, $t);
|
||||
|
||||
if( $tree2 ne '' ){
|
||||
@treelist = ($td1, $td2);
|
||||
}
|
||||
else {
|
||||
@treelist = ($td1);
|
||||
}
|
||||
|
||||
for $t (@treelist) {
|
||||
open(BUILDLOG, "<$t->{name}/build.dat" );
|
||||
while( <BUILDLOG> ){
|
||||
chop;
|
||||
($mailtime, $buildtime, $buildname, $errorparser, $buildstatus, $logfile, $binaryname) =
|
||||
split( /\|/ );
|
||||
|
||||
|
||||
$buildrec = {
|
||||
mailtime => $mailtime,
|
||||
buildtime => $buildtime,
|
||||
buildname => ($tree2 ne "" ? $t->{name} . " " : "" ) . $buildname,
|
||||
errorparser => $errorparser,
|
||||
buildstatus => $buildstatus,
|
||||
logfile => $logfile,
|
||||
binaryname => $binaryname,
|
||||
td => $t
|
||||
};
|
||||
if( $mailtime > 0 && $buildtime > $mindate ){
|
||||
push @{$build_list}, $buildrec;
|
||||
}
|
||||
}
|
||||
close( BUILDLOG );
|
||||
}
|
||||
}
|
||||
|
||||
sub load_who {
|
||||
local( $who_list, $td ) = @_;
|
||||
local($d,$w,$i,$bfound);
|
||||
|
||||
open(WHOLOG, "<$td->{name}/who.dat" );
|
||||
while( <WHOLOG> ){
|
||||
$i = $time_count;
|
||||
chop;
|
||||
($d,$w) = split(/\|/);
|
||||
$bfound = 0;
|
||||
while( $i > 0 && !$bfound ){
|
||||
if( $d <= $build_time_times->[$i] ){
|
||||
|
||||
$who_list->[$i+1]->{$w} = 1;
|
||||
$bfound = 1;
|
||||
}
|
||||
else {
|
||||
$i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
#
|
||||
# Ignore the last one
|
||||
#
|
||||
if( $time_count > 0 ){
|
||||
$who_list->[$time_count] = {};
|
||||
}
|
||||
}
|
||||
|
||||
sub get_build_name_index {
|
||||
local($i,$br);
|
||||
|
||||
#
|
||||
# Get all the unique build names.
|
||||
#
|
||||
for $br (@{$build_list}) {
|
||||
$build_name_index->{$br->{buildname}} = 1;
|
||||
}
|
||||
|
||||
|
||||
$i = 1;
|
||||
for $n (sort keys (%{$build_name_index})) {
|
||||
$build_name_names->[$i] = $n;
|
||||
$i++;
|
||||
}
|
||||
|
||||
$name_count = @{$build_name_names}-1;
|
||||
|
||||
|
||||
#
|
||||
# update the map so it points to the right index
|
||||
#
|
||||
$i = 1;
|
||||
while( $i < $name_count+1 ){
|
||||
$build_name_index->{$build_name_names->[$i]} = $i;
|
||||
#print "$name_count $build_name_names->[$i] $i <br>\n";
|
||||
$i++;
|
||||
}
|
||||
|
||||
#for $i (@{$build_name_names}) {
|
||||
# print "$build_name_names->[$i] $i <br>\n";
|
||||
#&}
|
||||
}
|
||||
|
||||
sub get_build_time_index {
|
||||
local($i,$br);
|
||||
|
||||
#
|
||||
# Get all the unique build names.
|
||||
#
|
||||
for $br (@{$build_list}) {
|
||||
$build_time_index->{$br->{buildtime}} = 1;
|
||||
#$build_time_index->{$br->{mailtime}} = 1;
|
||||
}
|
||||
|
||||
|
||||
$i = 1;
|
||||
for $n (sort {$b <=> $a} keys (%{$build_time_index})) {
|
||||
$build_time_times->[$i] = $n;
|
||||
$i++;
|
||||
}
|
||||
|
||||
$time_count = @{$build_time_times}-1;
|
||||
|
||||
|
||||
#
|
||||
# update the map so it points to the right index
|
||||
#
|
||||
$i = 1;
|
||||
while( $i < $time_count+1 ){
|
||||
$build_time_index->{$build_time_times->[$i]} = $i;
|
||||
$i++;
|
||||
}
|
||||
|
||||
#for $i (@{$build_time_times}) {
|
||||
# print $i . "\n";
|
||||
#}
|
||||
|
||||
#while( ($k,$v) = each(%{$build_time_index})) {
|
||||
# print "$k=$v\n";
|
||||
#}
|
||||
|
||||
}
|
||||
|
||||
sub make_build_table {
|
||||
local($i,$ti,$bi,$ti1,$br);
|
||||
$i = 1;
|
||||
|
||||
#
|
||||
# Create the build table
|
||||
#
|
||||
while( $i <= $time_count ){
|
||||
$build_table->[$i] = [];
|
||||
$i++;
|
||||
}
|
||||
|
||||
#
|
||||
# Populate the build table with build data
|
||||
#
|
||||
for $br (@{$build_list}) {
|
||||
$ti = $build_time_index->{$br->{buildtime}};
|
||||
$bi = $build_name_index->{$br->{buildname}};
|
||||
$build_table->[$ti][$bi] = $br;
|
||||
}
|
||||
|
||||
&load_notes;
|
||||
|
||||
$bi = $name_count;
|
||||
while( $bi > 0 ){
|
||||
$ti = $time_count;
|
||||
while( $ti > 0 ){
|
||||
if( defined( $br = $build_table->[$ti][$bi] )
|
||||
&& !defined( $br->{rowspan} )
|
||||
){
|
||||
#
|
||||
# If the cell immediatley after us is defined, then we
|
||||
# can have a previousbuildtime.
|
||||
#
|
||||
if( defined( $br1 = $build_table->[$ti+1][$bi] )){
|
||||
$br->{previousbuildtime} = $br1->{buildtime};
|
||||
}
|
||||
|
||||
$ti1 = $ti-1;
|
||||
while( $ti1 > 0
|
||||
&& !defined( $build_table->[$ti1][$bi] )
|
||||
#&& $build_time_times->[$ti1] < $br->{mailtime}
|
||||
){
|
||||
$build_table->[$ti1][$bi] = -1;
|
||||
$ti1--;
|
||||
}
|
||||
$br->{rowspan} = $ti - $ti1;
|
||||
if( $br->{rowspan} != 1 ){
|
||||
$build_table->[$ti1+1][$bi] = $br;
|
||||
$build_table->[$ti][$bi] = -1;
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
$ti--;
|
||||
}
|
||||
$bi--;
|
||||
}
|
||||
}
|
||||
|
||||
sub load_notes {
|
||||
if( $tree2 ne '' ){
|
||||
@treelist = ($td1, $td2);
|
||||
}
|
||||
else {
|
||||
@treelist = ($td1);
|
||||
}
|
||||
|
||||
for $t (@treelist) {
|
||||
open(NOTES,"<$t->{name}/notes.txt") || print "<h2>warning: Couldn't open $t->{name}/notes.txt </h2>\n";
|
||||
while(<NOTES>){
|
||||
chop;
|
||||
($nbuildtime,$nbuildname,$nwho,$nnow,$nenc_note) = split(/\|/);
|
||||
if( $tree2 ne "" ) { $nbuildname = $t->{name} . " " . $nbuildname; }
|
||||
$ti = $build_time_index->{$nbuildtime};
|
||||
$bi = $build_name_index->{$nbuildname};
|
||||
#print "[ti = $ti][bi=$bi][buildname='$nbuildname' $_<br>";
|
||||
if( $ti != 0 && $bi != 0 ){
|
||||
$build_table->[$ti][$bi]->{hasnote} = 1;
|
||||
if( ! defined($build_table->[$ti][$bi]->{noteid}) ){
|
||||
$build_table->[$ti][$bi]->{noteid} = (0+@note_array);
|
||||
}
|
||||
$noteid = $build_table->[$ti][$bi]->{noteid};
|
||||
$now_str = &print_time($nnow);
|
||||
$note = &url_decode($nenc_note);
|
||||
$note_array[$noteid] .=
|
||||
"<pre>\n[<b><a href=mailto:$nwho>$nwho</a> - $now_str</b>]\n$note\n</pre>";
|
||||
}
|
||||
}
|
||||
close(NOTES);
|
||||
}
|
||||
}
|
||||
|
||||
sub last_good_time {
|
||||
local($row) = @_;
|
||||
local($t,$currently_busted);
|
||||
|
||||
$t = 1;
|
||||
$isbusted = 0;
|
||||
while( $t <= $time_count ){
|
||||
if( defined( $build_table->[$t][$row] )){
|
||||
if( $build_table->[$t][$row]->{buildstatus} eq 'success' ){
|
||||
return {
|
||||
buildtime =>
|
||||
$build_time_times->[ $t +
|
||||
$build_table->[$t][$row]->{rowspan} ],
|
||||
isbusted => $isbusted };
|
||||
}
|
||||
elsif( $build_table->[$t][$row]->{buildstatus} eq 'busted' ){
|
||||
$isbusted = 1;
|
||||
}
|
||||
else {
|
||||
}
|
||||
}
|
||||
$t++;
|
||||
}
|
||||
return {buildtime => 0, isbusted => 1};
|
||||
}
|
||||
|
||||
|
||||
sub check_password {
|
||||
if ($form{'password'} eq "") {
|
||||
if (defined $cookie_jar{'tinderbox_password'}) {
|
||||
$form{'password'} = $cookie_jar{'tinderbox_password'};
|
||||
}
|
||||
}
|
||||
my $correct = "";
|
||||
if (open(REAL, "<data/passwd")) {
|
||||
$correct = <REAL>;
|
||||
close REAL;
|
||||
$correct =~ s/\s+$//; # Strip trailing whitespace.
|
||||
}
|
||||
if ($correct eq "") {
|
||||
return;
|
||||
}
|
||||
$form{'password'} =~ s/\s+$//; # Strip trailing whitespace.
|
||||
if ($form{'password'} ne "") {
|
||||
open(TRAPDOOR, "../bonsai/data/trapdoor $form{'password'} |") || die "Can't run trapdoor func!";
|
||||
my $encoded = <TRAPDOOR>;
|
||||
close TRAPDOOR;
|
||||
$encoded =~ s/\s+$//; # Strip trailing whitespace.
|
||||
if ($encoded eq $correct) {
|
||||
if ($form{'rememberpassword'} ne "") {
|
||||
print "Set-Cookie: tinderbox_password=$form{'password'} ; path=/ ; expires = Sun, 1-Mar-2020 00:00:00 GMT\n";
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
require 'header.pl';
|
||||
|
||||
print "Content-type: text/html\n";
|
||||
print "Set-Cookie: tinderbox_password= ; path=/ ; expires = Sun, 1-Mar-2020 00:00:00 GMT\n";
|
||||
print "\n";
|
||||
|
||||
EmitHtmlHeader("What's the magic word?",
|
||||
"You need to know the magic word to use this page.");
|
||||
|
||||
if ($form{'password'} ne "") {
|
||||
print "<B>Invalid password; try again.<BR></B>";
|
||||
}
|
||||
print "
|
||||
<FORM method=post>
|
||||
<B>Password:</B>
|
||||
<INPUT NAME=password TYPE=password><BR>
|
||||
<INPUT NAME=rememberpassword TYPE=checkbox> If correct, remember password as a cookie<BR>
|
||||
";
|
||||
|
||||
while (my ($key,$value) = each %form) {
|
||||
if ($key eq "password" || $key eq "rememberpassword") {
|
||||
next;
|
||||
}
|
||||
my $enc = value_encode($value);
|
||||
print "<INPUT TYPE=HIDDEN NAME=$key VALUE=\"$enc\">\n";
|
||||
}
|
||||
print "<INPUT TYPE=SUBMIT value=Submit></FORM>\n";
|
||||
exit;
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
# Figure out which directory tinderbox is in by looking at argv[0]
|
||||
|
||||
$tinderboxdir = $0;
|
||||
$tinderboxdir =~ s:/[^/]*$::; # Remove last word, and slash before it.
|
||||
if ($tinderboxdir eq "") {
|
||||
$tinderboxdir = ".";
|
||||
}
|
||||
|
||||
print "tinderbox = $tinderboxdir\n";
|
||||
|
||||
chdir $tinderboxdir || die "Couldn't chdir to $tinderboxdir";
|
||||
|
||||
|
||||
open(DF, ">data/tbx.$$") || die "could not open data/tbx.$$";
|
||||
while(<STDIN>){
|
||||
print DF $_;
|
||||
}
|
||||
close(DF);
|
||||
|
||||
$err = system("./processbuild.pl data/tbx.$$");
|
||||
|
||||
if( $err ) {
|
||||
die "processbuild.pl returned an error\n";
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
1;
|
||||
|
||||
sub add_imagelog {
|
||||
local($url,$quote,$width,$height) = @_;
|
||||
open( IMAGELOG, ">>$data_dir/imagelog.txt" ) || die "Oops; can't open imagelog.txt";
|
||||
print IMAGELOG "$url`$width`$height`$quote\n";
|
||||
close( IMAGELOG );
|
||||
}
|
||||
|
||||
sub get_image{
|
||||
local(@log,@ret,$i);
|
||||
|
||||
open( IMAGELOG, "<$data_dir/imagelog.txt" );
|
||||
@log = <IMAGELOG>;
|
||||
|
||||
# return a random line
|
||||
srand;
|
||||
@ret = split(/\`/,$log[rand @log]);
|
||||
|
||||
close( IMAGELOG );
|
||||
@ret;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<TITLE>tinderbox</TITLE>
|
||||
<META HTTP-EQUIV="Refresh" CONTENT="1; URL=showbuilds.cgi">
|
||||
<BODY BGCOLOR="#FFFFFF" TEXT="#000000"
|
||||
LINK="#0000EE" VLINK="#551A8B" ALINK="#FF0000">
|
||||
<CENTER>
|
||||
<TABLE BORDER=0 WIDTH="100%" HEIGHT="100%"><TR><TD ALIGN=CENTER VALIGN=CENTER>
|
||||
<FONT SIZE="+2">
|
||||
You're looking for
|
||||
<A HREF="showbuilds.cgi">showbuilds.cgi</A>.
|
||||
</FONT>
|
||||
</TD></TR></TABLE>
|
||||
</CENTER>
|
|
@ -0,0 +1,214 @@
|
|||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
require 'globals.pl';
|
||||
require 'timelocal.pl';
|
||||
|
||||
umask 0;
|
||||
|
||||
%MAIL_HEADER = ();
|
||||
%tbx = ();
|
||||
$logfile = '';
|
||||
|
||||
|
||||
&get_variables;
|
||||
&check_required_vars;
|
||||
&compress_log_file;
|
||||
&unlink_log_file;
|
||||
|
||||
$tree = $tbx{'tree'};
|
||||
|
||||
&lock;
|
||||
&write_build_data;
|
||||
&unlock;
|
||||
|
||||
$err = system("./buildwho.pl $tbx{'tree'}");
|
||||
|
||||
#
|
||||
# This routine will scan through log looking for 'tinderbox:' variables
|
||||
#
|
||||
sub get_variables{
|
||||
open( LOG, "<$ARGV[0]") || die "cant open $!";
|
||||
&parse_mail_header;
|
||||
|
||||
#while( ($k,$v) = each( %MAIL_HEADER ) ){
|
||||
# print "$k='$v'\n";
|
||||
#}
|
||||
|
||||
&parse_log_variables;
|
||||
|
||||
#while( ($k,$v) = each( %tbx ) ){
|
||||
# print "$k='$v'\n";
|
||||
#}
|
||||
close(LOG);
|
||||
}
|
||||
|
||||
|
||||
sub parse_log_variables {
|
||||
while($line = <LOG> ){
|
||||
chop($line);
|
||||
if( $line =~ /^tinderbox\:/ ){
|
||||
if( $line =~ /^tinderbox\:[ \t]*([^:]*)\:[ \t]*([^\n]*)/ ){
|
||||
$tbx{$1} = $2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub parse_mail_header {
|
||||
while($line = <LOG> ){
|
||||
chop($line);
|
||||
|
||||
if( $line eq '' ){
|
||||
return;
|
||||
}
|
||||
|
||||
if( $line =~ /([^ :]*)\:[ \t]+([^\n]*)/ ){
|
||||
$name = $1;
|
||||
$MAIL_HEADER{$name} = $2;
|
||||
#print "$name $2\n";
|
||||
}
|
||||
elsif( $name ne '' ){
|
||||
$MAIL_HEADER{$name} .= $2;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sub check_required_vars {
|
||||
$err_string = '';
|
||||
if( $tbx{'tree'} eq ''){
|
||||
$err_string .= "Variable 'tinderbox:tree' not set.\n";
|
||||
}
|
||||
elsif( ! -r $tbx{'tree'} ){
|
||||
$err_string .= "Variable 'tinderbox:tree' not set to a valid tree.\n";
|
||||
}
|
||||
if( $tbx{'build'} eq ''){
|
||||
$err_string .= "Variable 'tinderbox:build' not set.\n";
|
||||
}
|
||||
if( $tbx{'errorparser'} eq ''){
|
||||
$err_string .= "Variable 'tinderbox:errorparser' not set.\n";
|
||||
}
|
||||
|
||||
#
|
||||
# Grab the date in the form of mm/dd/yy hh:mm:ss
|
||||
#
|
||||
# Or a GMT unix date
|
||||
#
|
||||
if( $tbx{'builddate'} eq ''){
|
||||
$err_string .= "Variable 'tinderbox:builddate' not set.\n";
|
||||
}
|
||||
else {
|
||||
if( $tbx{'builddate'} =~
|
||||
/([0-9]*)\/([0-9]*)\/([0-9]*)[ \t]*([0-9]*)\:([0-9]*)\:([0-9]*)/ ){
|
||||
|
||||
$builddate = timelocal($6,$5,$4,$2,$1-1,$3);
|
||||
|
||||
}
|
||||
elsif( $tbx{'builddate'} > 7000000 ){
|
||||
$builddate = $tbx{'builddate'};
|
||||
}
|
||||
else {
|
||||
$err_string .= "Variable 'tinderbox:builddate' not of the form MM/DD/YY HH:MM:SS or unix date\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#
|
||||
# Build Status
|
||||
#
|
||||
if( $tbx{'status'} eq ''){
|
||||
$err_string .= "Variable 'tinderbox:status' not set.\n";
|
||||
}
|
||||
elsif( ! $tbx{'status'} =~ /success|busted|building/ ){
|
||||
$err_string .= "Variable 'tinderbox:status' must be 'success', 'busted' or 'building'\n";
|
||||
}
|
||||
|
||||
#
|
||||
# Report errors
|
||||
#
|
||||
if( $err_string ne '' ){
|
||||
die $err_string;
|
||||
}
|
||||
}
|
||||
|
||||
sub write_build_data {
|
||||
$t = time;
|
||||
open( BUILDDATA, ">>$tbx{'tree'}/build.dat" )|| die "can't open $! for writing";
|
||||
print BUILDDATA "$t|$builddate|$tbx{'build'}|$tbx{'errorparser'}|$tbx{'status'}|$logfile|$tbx{binaryname}\n";
|
||||
close( BUILDDATA );
|
||||
}
|
||||
|
||||
sub compress_log_file {
|
||||
local( $done, $line);
|
||||
|
||||
if( $tbx{'status'} =~ /building/ ){
|
||||
return;
|
||||
}
|
||||
|
||||
open( LOG2, "<$ARGV[0]") || die "cant open $!";
|
||||
|
||||
#
|
||||
# Skip past the the RFC822.HEADER
|
||||
#
|
||||
$done = 0;
|
||||
while( !$done && ($line = <LOG2>) ){
|
||||
chop($line);
|
||||
$done = ($line eq '');
|
||||
}
|
||||
|
||||
$logfile = "$$.gz";
|
||||
|
||||
open( ZIPLOG, "| $gzip -c > $tbx{'tree'}/$logfile" ) || die "can't open $! for writing";
|
||||
$inBinary = 0;
|
||||
$hasBinary = ($tbx{'binaryname'} ne '');
|
||||
while( $line = <LOG2> ){
|
||||
if( !$inBinary ){
|
||||
print ZIPLOG $line;
|
||||
if( $hasBinary ){
|
||||
$inBinary = ($line =~ /^begin [0-7][0-7][0-7] /);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if( $line =~ /^end\n/ ){
|
||||
$inBinary = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
close( ZIPLOG );
|
||||
close( LOG2 );
|
||||
|
||||
#
|
||||
# If a uuencoded binary is part of the build, unpack it.
|
||||
#
|
||||
if( $hasBinary ){
|
||||
$bin_dir = "$tbx{'tree'}/bin/$builddate/$tbx{'build'}";
|
||||
$bin_dir =~ s/ //g;
|
||||
|
||||
system("mkdir -m 0777 -p $bin_dir");
|
||||
|
||||
# LTNOTE: I'm not sure this is cross platform.
|
||||
system("/tools/ns/bin/uudecode --output-file=$bin_dir/$tbx{binaryname} < $ARGV[0]");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub unlink_log_file {
|
||||
unlink( $ARGV[0] );
|
||||
}
|
|
@ -0,0 +1,552 @@
|
|||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
use lib "../bonsai";
|
||||
|
||||
require 'globals.pl';
|
||||
require 'lloydcgi.pl';
|
||||
require 'imagelog.pl';
|
||||
require 'header.pl';
|
||||
$|=1;
|
||||
|
||||
print "Content-type: text/html\n\n<HTML>\n";
|
||||
|
||||
|
||||
#
|
||||
# show 36 hours by default
|
||||
#
|
||||
if($form{'showall'} != 0 ){
|
||||
$mindate = 0;
|
||||
}
|
||||
else {
|
||||
$hours = 36;
|
||||
if( $form{hours} ne "" ){
|
||||
$hours = $form{hours};
|
||||
}
|
||||
$mindate = time - ($hours*60*60);
|
||||
}
|
||||
|
||||
$colormap = {
|
||||
success => '00ff00',
|
||||
busted => 'red',
|
||||
building => 'yellow'
|
||||
};
|
||||
|
||||
#
|
||||
# Debug hack
|
||||
#
|
||||
#$form{'tree'} = DogbertTip;
|
||||
$tree = $form{'tree'};
|
||||
|
||||
if( $form{'tree'} eq '' ){
|
||||
&show_tree_selector;
|
||||
}
|
||||
else {
|
||||
if( $form{'express'} ) {
|
||||
&do_express;
|
||||
}
|
||||
else {
|
||||
&load_data;
|
||||
&load_javascript;
|
||||
&display_page_head;
|
||||
&display_build_table;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub show_tree_selector {
|
||||
|
||||
EmitHtmlHeader("tinderbox");
|
||||
|
||||
print "<P><TABLE WIDTH=\"100%\">";
|
||||
print "<TR><TD ALIGN=CENTER>Select one of the following trees:</TD></TR>";
|
||||
print "<TR><TD ALIGN=CENTER>\n";
|
||||
print " <TABLE><TR><TD><UL>\n";
|
||||
|
||||
while(<*>) {
|
||||
if( -d $_ && $_ ne 'data' && $_ ne 'CVS' ){
|
||||
print "<LI><a href=showbuilds.cgi?tree=$_>$_</a>\n";
|
||||
}
|
||||
}
|
||||
print "<//UL></TD></TR></TABLE></TD></TR></TABLE>";
|
||||
}
|
||||
|
||||
|
||||
|
||||
sub display_page_head {
|
||||
|
||||
my ($imageurl,$imagewidth,$imageheight,$quote) = &get_image;
|
||||
|
||||
|
||||
# srand;
|
||||
# $when = 60*10 + int rand(60*40);
|
||||
# <META HTTP-EQUIV=\"REFRESH\" CONTENT=\"$when\">
|
||||
|
||||
|
||||
if( -r "$tree/mod.pl" ){
|
||||
require "$tree/mod.pl";
|
||||
}
|
||||
else {
|
||||
$message_of_day = "";
|
||||
}
|
||||
|
||||
$treename = $tree . ($tree2 ne "" ? " and $tree2" : "" );
|
||||
|
||||
EmitHtmlTitleAndHeader("tinderbox: $treename", "tinderbox",
|
||||
"tree: $treename");
|
||||
|
||||
|
||||
print "$script_str\n";
|
||||
print "$message_of_day\n";
|
||||
|
||||
print "<table width='100%'>";
|
||||
print "<tr>";
|
||||
print "<td valign=bottom>";
|
||||
print "<p><center><a href=addimage.cgi><img src='$imageurl' ";
|
||||
print "width=$imagewidth height=$imageheight><br>";
|
||||
print "$quote</a><br>";
|
||||
print "</center>";
|
||||
print "<p>";
|
||||
print "<td align=right valign=bottom>";
|
||||
print "<table><tr><td>";
|
||||
print "<TT>L</TT> = Show Build Log<br>";
|
||||
print "<TT><img src=star.gif>L</TT> = Show Log comments<br>";
|
||||
print "<TT>C</TT> = Show changes that occured since the last build<br>";
|
||||
print "<TT>B</TT> = Download binary generated by the build<br>";
|
||||
print "<table cellspacing=2 border>";
|
||||
print "<tr bgcolor=yellow><td>Currently Building";
|
||||
print "<tr bgcolor=00ff00><td>Built successfully";
|
||||
print "<tr bgcolor=red><td>Build failed";
|
||||
print "</table>";
|
||||
print "</td></tr></table>";
|
||||
print "</table>";
|
||||
|
||||
if( $form{'tree'} eq 'MercuryTip' || $form{'tree'} eq 'FreeSource'){
|
||||
print "<p>The tree is currently <font size=+2>";
|
||||
if( &tree_open ){
|
||||
print "OPEN";
|
||||
}
|
||||
else {
|
||||
print "CLOSED";
|
||||
}
|
||||
print "</font>\n";
|
||||
}
|
||||
}
|
||||
|
||||
sub display_build_table {
|
||||
&display_build_table_header;
|
||||
&display_build_table_body;
|
||||
&display_build_table_footer;
|
||||
|
||||
}
|
||||
|
||||
sub display_build_table_body {
|
||||
local($t);
|
||||
|
||||
$t = 1;
|
||||
while( $t <= $time_count ){
|
||||
display_build_table_row( $t );
|
||||
$t++;
|
||||
}
|
||||
}
|
||||
|
||||
sub display_build_table_row {
|
||||
local($t) = @_;
|
||||
local($tt);
|
||||
$tt = &print_time($build_time_times->[$t]);
|
||||
|
||||
if( $tree2 ne "" ){
|
||||
$qr = "";
|
||||
$er = "";
|
||||
}
|
||||
else {
|
||||
$qr = &query_ref( $td1, $build_time_times->[$t]);
|
||||
$er = "</a>";
|
||||
}
|
||||
|
||||
if ($build_time_times->[$t] % 7200 > 3600) {
|
||||
$color = "white";
|
||||
} else {
|
||||
$color = "beige";
|
||||
}
|
||||
|
||||
print "<tr align=center>\n";
|
||||
print "<td bgcolor=$color>${qr}\n${tt}${er}\n";
|
||||
|
||||
|
||||
if( $tree2 ne "" ){
|
||||
print "<td align=center bgcolor=beige>\n";
|
||||
$qr = &query_ref( $td1, $build_time_times->[$t]);
|
||||
print "${qr}<tt><b>X</b></tt></a>\n";
|
||||
}
|
||||
|
||||
print "<td align=center>\n";
|
||||
|
||||
for $who (sort keys %{$who_list->[$t]} ){
|
||||
#$qr = &query_ref( $td1, $build_time_times->[$t],$build_time_times->[$t-1],$who);
|
||||
$qr = &who_menu( $td1, $build_time_times->[$t],$build_time_times->[$t-1],$who);
|
||||
print " ${qr}$who</a>\n";
|
||||
}
|
||||
|
||||
if( $tree2 ne "" ){
|
||||
print "<td align=cenger bgcolor=beige >\n";
|
||||
$qr = &query_ref( $td2, $build_time_times->[$t]);
|
||||
print "${qr}<tt><b>X</b></tt></a>\n";
|
||||
|
||||
print "<td align=center>\n";
|
||||
|
||||
for $who (sort keys %{$who_list2->[$t]} ){
|
||||
#$qr = &query_ref( $td2, $build_time_times->[$t],$build_time_times->[$t-1],$who);
|
||||
$qr = &who_menu( $td2, $build_time_times->[$t],$build_time_times->[$t-1],$who);
|
||||
print " ${qr}$who</a>\n";
|
||||
}
|
||||
}
|
||||
|
||||
$bn = 1;
|
||||
while( $bn <= $name_count ){
|
||||
if( defined($br = $build_table->[$t][$bn])){
|
||||
if( $br != -1 ){
|
||||
|
||||
$hasnote = $br->{hasnote};
|
||||
$noteid = $hasnote ? $br->{noteid} : 0;
|
||||
$rowspan = $br->{rowspan};
|
||||
$color = $colormap->{$br->{buildstatus}};
|
||||
$status = $br->{buildstatus};
|
||||
print "<td rowspan=$rowspan bgcolor=${color}>\n";
|
||||
|
||||
$logfile = $br->{logfile};
|
||||
$errorparser = $br->{errorparser};
|
||||
$buildname = $br->{buildname};
|
||||
if( $tree2 ne "" ){
|
||||
$buildname =~ s/^[^ ]* //;
|
||||
}
|
||||
$buildname = &url_encode($buildname);
|
||||
$buildtime = $br->{buildtime};
|
||||
$buildtree = $br->{td}->{name};
|
||||
|
||||
print "<tt>\n";
|
||||
|
||||
if( $hasnote ){
|
||||
print "<a href='' onClick=\"return js_what_menu(event,$noteid,'$logfile','$errorparser','$buildname','$buildtime');\">";
|
||||
print "<img src=star.gif border=0></a>\n";
|
||||
}
|
||||
print "<a href='showlog.cgi?logfile=$logfile\&tree=$buildtree\&errorparser=$errorparser&buildname=$buildname&buildtime=$buildtime&mainframe=1'>\n";
|
||||
print "L</a>\n";
|
||||
|
||||
#print "Build Summary</a><br>\n";
|
||||
|
||||
if( $br->{previousbuildtime} ){
|
||||
$qr = &query_ref($br->{td}, $br->{previousbuildtime},$br->{buildtime});
|
||||
print "$qr\n";
|
||||
print " C</a>\n";
|
||||
#print "What Changed</a><br>\n";
|
||||
}
|
||||
|
||||
if( $br->{binaryname} ne '' ){
|
||||
$binfile = "$buildtree/bin/$buildtime/$br->{buildname}/$br->{binaryname}";
|
||||
$binfile =~ s/ //g;
|
||||
print " <a href=$binfile>B</a>";
|
||||
}
|
||||
print "</tt>\n";
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
else {
|
||||
print "<td> \n";
|
||||
}
|
||||
$bn++;
|
||||
}
|
||||
|
||||
|
||||
print "</tr>\n";
|
||||
}
|
||||
|
||||
|
||||
sub display_build_table_header {
|
||||
local($i,$nspan);
|
||||
|
||||
print "<TABLE border cellspacing=2>\n";
|
||||
|
||||
print "<tr align=center>\n";
|
||||
print "<td rowspan=1><font size=-1>Click time to <br>see changes <br>since time</font>";
|
||||
$nspan = ( $tree2 ne "" ? 4 : 1);
|
||||
print "<td colspan=$nspan><font size=-1>Click name to see what they did</font>";
|
||||
#print "<td colspan=$name_count><font size=-1>Burning builds are busted</font>";
|
||||
#print "</tr>\n";
|
||||
|
||||
|
||||
#print "<tr>\n";
|
||||
$i = 1;
|
||||
while ($i <= $name_count){
|
||||
|
||||
$bn = $build_name_names->[$i];
|
||||
$bn =~ s/Clobber/Clbr/g;
|
||||
$bn =~ s/Depend/Dep/g;
|
||||
$t = &last_good_time($i);
|
||||
|
||||
if( $form{'narrow'} ){
|
||||
$bn =~ s/([^:])/$1<br>/g;
|
||||
$bn = "<tt>$bn</tt>";
|
||||
}
|
||||
else {
|
||||
$bn = "<font face='Arial,Helvetica' size=-2>$bn</font>";
|
||||
|
||||
}
|
||||
|
||||
if( $t->{isbusted} ){
|
||||
print "<td rowspan=2 bgcolor=000000 background=1afi003r.gif>";
|
||||
print "<font color=white>$bn</font>\n";
|
||||
#print "<img src=reledanim.gif>\n";
|
||||
}
|
||||
else {
|
||||
print "<th rowspan=2 bgcolor=00ff00>";
|
||||
print "$bn\n";
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
print "</tr>\n";
|
||||
|
||||
print "<tr>\n";
|
||||
print "<b><TH>Build Time\n";
|
||||
if( $tree2 ne "" ){
|
||||
print "<TH colspan=2>$td1->{name}\n";
|
||||
print "<TH colspan=2>$td2->{name}\n";
|
||||
}
|
||||
else {
|
||||
print "<TH>Guilty\n";
|
||||
}
|
||||
print "</b></tr>\n";
|
||||
|
||||
}
|
||||
|
||||
sub display_build_table_footer {
|
||||
print "</table>\n";
|
||||
print "<a href=showbuilds.cgi?tree=$tree&showall=1.cgi>Show more checkin history</a><br><br>\n";
|
||||
|
||||
if (open(FOOTER, "<$data_dir/footer.html")) {
|
||||
while (<FOOTER>) {
|
||||
print $_;
|
||||
}
|
||||
close FOOTER;
|
||||
}
|
||||
print "<a href=admintree.cgi?tree=$tree>Administrate Tinderbox Trees</a><br>";
|
||||
|
||||
print "<br><br>";
|
||||
}
|
||||
|
||||
|
||||
sub query_ref {
|
||||
local( $td, $mindate, $maxdate, $who ) = @_;
|
||||
|
||||
return "<a href=../bonsai/cvsquery.cgi?module=$td->{cvs_module}&branch=$td->{cvs_branch}&cvsroot=$td->{cvs_root}&date=explicit&mindate=$mindate&maxdate=$maxdate&who=$who>";
|
||||
}
|
||||
|
||||
sub query_ref2 {
|
||||
local( $td, $mindate, $maxdate, $who ) = @_;
|
||||
return "../bonsai/cvsquery.cgi?module=$td->{cvs_module}&branch=$td->{cvs_branch}&cvsroot=$td->{cvs_root}&date=explicit&mindate=$mindate&maxdate=$maxdate&who=$who";
|
||||
}
|
||||
|
||||
|
||||
sub who_menu {
|
||||
local( $td, $mindate, $maxdate, $who ) = @_;
|
||||
my $treeflag;
|
||||
#$qr="../bonsai/cvsquery.cgi?module=$td->{cvs_module}&branch=$td->{cvs_branch}&cvsroot=$td->{cvs_root}&date=explicit&mindate=$mindate&maxdate=$maxdate&who=$who";
|
||||
$qr = "../registry/who.cgi?email=$who"
|
||||
. "&t0=" . &url_encode("What did $who check into the source tree" )
|
||||
. "&u0=" . &url_encode( &query_ref2($td,$mindate,$maxdate,$who) )
|
||||
. "&t1=" . &url_encode("What has $who been checking in in the last day" )
|
||||
. "&u1=" . &url_encode( &query_ref2($td,$mindate,$maxdate,$who) );
|
||||
|
||||
return "<a href='$qr' onClick=\"return js_who_menu($td->{num},'$who',event,$mindate,$maxdate);\" >";
|
||||
}
|
||||
|
||||
|
||||
sub tree_open {
|
||||
open( BID, "<../bonsai/data/batchid") || print "can't open batchid<br>";
|
||||
($a,$b,$bid) = split(/ /,<BID>);
|
||||
close( BID );
|
||||
open( BATCH, "<../bonsai/data/batch-${bid}") || print "can't open batch-${bid}<br>";;
|
||||
$done = 0;
|
||||
while( ($line = <BATCH>) && !$done ){
|
||||
if($line =~ /^set treeopen/) {
|
||||
chop( $line );
|
||||
($a,$b,$treestate) = split(/ /, $line );
|
||||
$done = 1;
|
||||
}
|
||||
}
|
||||
close( BATCH );
|
||||
return $treestate;
|
||||
}
|
||||
|
||||
sub load_javascript {
|
||||
|
||||
$script_str =<<'ENDJS';
|
||||
<script>
|
||||
|
||||
|
||||
if( parseInt(navigator.appVersion) < 4 ){
|
||||
window.event = 0;
|
||||
}
|
||||
|
||||
|
||||
function js_who_menu(tree,n,d,mindate,maxdate) {
|
||||
if( parseInt(navigator.appVersion) < 4 ){
|
||||
return true;
|
||||
}
|
||||
|
||||
l = document.layers['popup'];
|
||||
l.src = "../registry/who.cgi?email=" + n
|
||||
+ "&t0=" + escape("Last check-in" )
|
||||
+ "&u0=" + escape( js_qr(tree,mindate,maxdate,n) )
|
||||
+ "&t1=" + escape("Check-ins within 24 hours" )
|
||||
+ "&u1=" + escape( js_qr24(tree,n) );
|
||||
|
||||
//l.document.write(
|
||||
// "<table border=1 cellspacing=1><tr><td>" +
|
||||
// js_qr(mindate,maxdate,n) + "What did " + n + " <b>check in to the source tree</b>?</a><br>" +
|
||||
// js_qr24(n) +"What has " + n + " <b>been checking in over the last day</b>?</a> <br>" +
|
||||
// "<a href=https://endor.mcom.com/ds/dosearch/endor.mcom.com/uid%3D" +n + "%2Cou%3DPeople%2Co%3DNetscape%20Communications%20Corp.%2Cc%3DUS>" +
|
||||
// "Who is <b>" + n + "</b> and how do <b>I wake him/her up</b></a>?<br>" +
|
||||
// "<a href='mailto:" + n + "?subject=Whats up with...'>Send mail to <b>" + n + "</b></a><br>" +
|
||||
// "<a href=http://dome/locator/findUser.cgi?email="+n+">Where is <b>"+n+"'s office?</b></a>" +
|
||||
// "</tr></table>");
|
||||
//l.document.close();
|
||||
|
||||
//alert( d.y );
|
||||
l.top = d.target.y - 6;
|
||||
l.left = d.target.x - 6;
|
||||
if( l.left + l.clipWidth > window.width ){
|
||||
l.left = window.width - l.clipWidth;
|
||||
}
|
||||
l.visibility="show";
|
||||
return false;
|
||||
}
|
||||
|
||||
function js_what_menu(d,noteid,logfile,errorparser,buildname,buildtime) {
|
||||
if( parseInt(navigator.appVersion) < 4 ){
|
||||
return true;
|
||||
}
|
||||
|
||||
l = document.layers['popup'];
|
||||
l.document.write(
|
||||
"<table border=1 cellspacing=1><tr><td>" +
|
||||
note_array[noteid] +
|
||||
"</tr></table>");
|
||||
l.document.close();
|
||||
|
||||
l.top = d.y-10;
|
||||
zz = d.x;
|
||||
//alert( l.clip.right+ " " + (window.innerWidth -30) );
|
||||
if( zz + l.clip.right > window.innerWidth ){
|
||||
zz = (window.innerWidth-30) - l.clip.right;
|
||||
if( zz < 0 ){
|
||||
zz = 0;
|
||||
}
|
||||
|
||||
}
|
||||
l.left = zz;
|
||||
l.visibility="show";
|
||||
return false;
|
||||
}
|
||||
|
||||
note_array = new Array();
|
||||
|
||||
</script>
|
||||
|
||||
<layer name="popup" onMouseOut="this.visibility='hide';" left=0 top=0 bgcolor="#ffffff" visibility="hide">
|
||||
</layer>
|
||||
|
||||
ENDJS
|
||||
|
||||
$script_str .= "
|
||||
<script>
|
||||
|
||||
function js_qr(tree,mindate, maxdate, who ){
|
||||
if (tree == 0 ){
|
||||
return '../bonsai/cvsquery.cgi?module=${cvs_module}&branch=${cvs_branch}&cvsroot=${cvs_root}&date=explicit&mindate='
|
||||
+ mindate + '&maxdate=' +maxdate + '&who=' + who ;
|
||||
}
|
||||
else {
|
||||
return '../bonsai/cvsquery.cgi?module=$td2->{cvs_module}&branch=$td2->{cvs_branch}&cvsroot=$td2->{cvs_root}&date=explicit&mindate='
|
||||
+ mindate + '&maxdate=' +maxdate + '&who=' + who ;
|
||||
}
|
||||
}
|
||||
|
||||
function js_qr24(tree,who){
|
||||
if (tree == 0 ){
|
||||
return '../bonsai/cvsquery.cgi?module=${cvs_module}&branch=${cvs_branch}&cvsroot=${cvs_root}&date=day'
|
||||
+ '&who=' +who;
|
||||
}
|
||||
else{
|
||||
return '../bonsai/cvsquery.cgi?module=$td2->{cvs_module}&branch=$td2->{cvs_branch}&cvsroot=$td2->{cvs_root}&date=day'
|
||||
+ '&who=' +who;
|
||||
}
|
||||
}
|
||||
";
|
||||
|
||||
$i = 0;
|
||||
while( $i < @note_array ){
|
||||
$s = $note_array[$i];
|
||||
$s =~ s/\\/\\\\/g;
|
||||
$s =~ s/\"/\\\"/g;
|
||||
$s =~ s/\n/\\n/g;
|
||||
$script_str .= "note_array[$i] = \"$s\";\n";
|
||||
$i++;
|
||||
}
|
||||
|
||||
$script_str .= "</script>\n";
|
||||
|
||||
}
|
||||
|
||||
|
||||
sub do_express {
|
||||
local($mailtime, $buildtime, $buildname, $errorparser, $buildstatus, $logfile);
|
||||
local($buildrec);
|
||||
local(%build);
|
||||
|
||||
open(BUILDLOG, "<$form{'tree'}/build.dat" ) || die ;
|
||||
while( <BUILDLOG> ){
|
||||
chop;
|
||||
($mailtime, $buildtime, $buildname, $errorparser, $buildstatus, $logfile) =
|
||||
split( /\|/ );
|
||||
if( $buildstatus eq 'success' || $buildstatus eq 'busted'){
|
||||
$build{$buildname} = $buildstatus;
|
||||
}
|
||||
}
|
||||
close( BUILDLOG );
|
||||
|
||||
@keys = sort keys %build;
|
||||
$keycount = @keys;
|
||||
$treename = $form{tree};
|
||||
$tm = &print_time(time);
|
||||
print "<table border=1 align=center><tr><th colspan=$keycount><a href=showbuilds.cgi?tree=$treename>$tree as of $tm</a></tr>"
|
||||
."<tr>\n";
|
||||
for $buildname (@keys ){
|
||||
if( $build{$buildname} eq 'success' ){
|
||||
print "<td bgcolor=00ff00>";
|
||||
}
|
||||
else {
|
||||
print "<td bgcolor=000000 background=1afi003r.gif>";
|
||||
print "<font color=white>\n";
|
||||
}
|
||||
print "$buildname";
|
||||
}
|
||||
print "</tr></table>\n";
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
|
||||
$| = 1;
|
||||
|
||||
use lib "../bonsai";
|
||||
|
||||
require 'globals.pl';
|
||||
require 'imagelog.pl';
|
||||
require 'lloydcgi.pl';
|
||||
require 'header.pl';
|
||||
|
||||
check_password();
|
||||
|
||||
print "Content-type: text/html\n\n";
|
||||
|
||||
@url = ();
|
||||
@quote = ();
|
||||
@width = ();
|
||||
@height = ();
|
||||
$i = 0;
|
||||
|
||||
EmitHtmlHeader("tinderbox: all images");
|
||||
|
||||
print '<UL>
|
||||
<P>These are all of the images currently in
|
||||
<A HREF=http://www.mozilla.org/tinderbox.html>Tinderbox</A>.
|
||||
<P>Please don\'t give out this URL: this is only here for our debugging
|
||||
needs, and isn\'t linked to by the rest of Tinderbox: because looking at
|
||||
all the images at once would be be cheating! you\'re supposed to let them
|
||||
surprise you over time. What, do you read ahead in your desktop calendar,
|
||||
too? Where\'s your sense of mystery and anticipation?
|
||||
|
||||
<P>
|
||||
</UL>
|
||||
';
|
||||
|
||||
|
||||
|
||||
|
||||
if ($form{'url'} ne "") {
|
||||
$oldname = "$data_dir/imagelog.txt";
|
||||
open (OLD, "<$oldname") || die "Oops; can't open imagelog.txt";
|
||||
$newname = "$oldname-$$";
|
||||
open (NEW, ">$newname") || die "Can't open $newname";
|
||||
$foundit = 0;
|
||||
while (<OLD>) {
|
||||
chop;
|
||||
($url, $width, $height, $quote) = split(/\`/);
|
||||
if ($url eq $form{'url'} && $quote eq $form{'origquote'}) {
|
||||
$foundit = 1;
|
||||
if ($form{'nukeit'} ne "") {
|
||||
next;
|
||||
}
|
||||
$quote = $form{'quote'};
|
||||
}
|
||||
print NEW "$url`$width`$height`$quote\n";
|
||||
}
|
||||
close OLD;
|
||||
close NEW;
|
||||
if (!$foundit) {
|
||||
print "<font color=red>Hey, couldn't find it!</font> Did someone\n";
|
||||
print "else already edit it?<P>\n";
|
||||
unlink $newname;
|
||||
} else {
|
||||
print "Change made.<P>";
|
||||
rename ($newname, $oldname) || die "Couldn't rename $newname to $oldname";
|
||||
}
|
||||
$form{'doedit'} = "1";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
$doedit = ($form{'doedit'} ne "");
|
||||
|
||||
if (!$doedit) {
|
||||
print "
|
||||
<form method=post>
|
||||
<input type=hidden name=password value=\"$form{'password'}\">
|
||||
<input type=hidden name=doedit value=1>
|
||||
<input type=submit value='Let me edit text or remove pictures.'>
|
||||
</form><P>";
|
||||
}
|
||||
|
||||
|
||||
|
||||
open( IMAGELOG, "<$data_dir/imagelog.txt" ) || die "can't open file";
|
||||
while( <IMAGELOG> ){
|
||||
chop;
|
||||
($url[$i],$width[$i],$height[$i],$quote[$i]) = split(/\`/);
|
||||
$i++;
|
||||
}
|
||||
close( IMAGELOG );
|
||||
|
||||
$i--;
|
||||
print "<center>";
|
||||
while( $i >= 0 ){
|
||||
$qurl = value_encode($url[$i]);
|
||||
$qquote = value_encode($quote[$i]);
|
||||
print "
|
||||
<img border=2 src='$url[$i]' width='$width[$i]' height='$height[$i]'><br>
|
||||
<i>$quote[$i]</i>";
|
||||
if ($doedit) {
|
||||
print "
|
||||
<form method=post>
|
||||
<input type=submit name=nukeit value='Delete this image'><br>
|
||||
<input name=quote size=60 value=\"$qquote\"><br>
|
||||
<input type=submit name=edit value='Change text'><hr>
|
||||
<input type=hidden name=url value=\"$qurl\">
|
||||
<input type=hidden name=origquote value=\"$qquote\">
|
||||
<input type=hidden name=password value=\"$form{'password'}\">
|
||||
</form>";
|
||||
}
|
||||
print "<br><br>\n";
|
||||
$i--;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,282 @@
|
|||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.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.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
use lib "../bonsai";
|
||||
|
||||
require 'globals.pl';
|
||||
require 'lloydcgi.pl';
|
||||
require 'header.pl';
|
||||
|
||||
|
||||
$|=1;
|
||||
|
||||
$LINES_AFTER_ERROR = 5;
|
||||
$LINES_BEFORE_ERROR = 30;
|
||||
|
||||
$error_file = '';
|
||||
$error_file_ref = '';
|
||||
$error_line = 0;
|
||||
$error_guess = 0;
|
||||
|
||||
print "Content-type: text/html\n\n";
|
||||
|
||||
$error_count = 0;
|
||||
|
||||
$next_err = 0;
|
||||
|
||||
@log_errors = ();
|
||||
$log_ln = 0;
|
||||
|
||||
if (1) {
|
||||
$tree = $form{'tree'};
|
||||
$errorparser = $form{'errorparser'};
|
||||
$logfile = $form{'logfile'};
|
||||
$summary = $form{'summary'};
|
||||
$buildname = $form{'buildname'};
|
||||
$buildtime = $form{'buildtime'};
|
||||
$enc_buildname = &url_encode($buildname);
|
||||
$frames = $form{'frames'};
|
||||
$fulltext = $form{'fulltext'};
|
||||
$mainframe = $form{'mainframe'};
|
||||
#print "$buildname \n $buildtime \n $errorparser \n $logfile \n $tree \n $enc_buildname \n";
|
||||
}
|
||||
else {
|
||||
$tree = 'FreeSource';
|
||||
$errorparser = 'windows';
|
||||
$logfile = '19692.gz';
|
||||
}
|
||||
|
||||
die "the \"tree\" parameter must be provided\n" unless $tree;
|
||||
require "$tree/treedata.pl";
|
||||
|
||||
if( $mainframe ){
|
||||
print "
|
||||
<HTML>
|
||||
<FRAMESET name = main ROWS='70%, 30%'>
|
||||
<FRAME NAME='log' SCROLL=AUTO SRC='showlog.cgi?tree=$tree&errorparser=$errorparser&logfile=$logfile&summary=$summary&buildtime=$buildtime&buildname=$enc_buildname&fulltext=$fulltext&frames=1'>
|
||||
<FRAME NAME='SOURCEFRAME' SCROLL='AUTO' SRC='Empty.html'>
|
||||
</FRAMESET>
|
||||
</HTML>
|
||||
";
|
||||
exit 0;
|
||||
}
|
||||
|
||||
if( $frames ){
|
||||
$source_target = "target=SOURCEFRAME";
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Dynamically load the error parser
|
||||
#
|
||||
die "the \"errorparser\" parameter must be provided\n" unless $errorparser;
|
||||
require "ep_${errorparser}.pl";
|
||||
|
||||
$time_str = print_time( $form{'buildtime'} );
|
||||
|
||||
if( $fulltext ){
|
||||
$s = 'Show <b>Brief</b> Log';
|
||||
$s1 = '';
|
||||
$s2 = 'Full';
|
||||
}
|
||||
else {
|
||||
$s = 'Show <b>Full</b> Log';
|
||||
$s1 = 1;
|
||||
$s2 = 'Brief';
|
||||
}
|
||||
|
||||
print "<META HTTP-EQUIV=\"EXPIRES\" CONTENT=\"1\">\n";
|
||||
|
||||
my $heading = "Build Log ($s2)";
|
||||
my $subheading = "$form{'buildname'} on $time_str";
|
||||
my $title = "$heading - $subheading";
|
||||
|
||||
EmitHtmlTitleAndHeader($title, $heading, $subheading);
|
||||
|
||||
print "
|
||||
<font size=+1>
|
||||
<dt><a href='showlog.cgi?tree=$tree&errorparser=$errorparser&logfile=$logfile&summary=$summary&buildtime=$buildtime&buildname=$enc_buildname&fulltext=$s1&frames=1'>$s</a>
|
||||
<dt><a href=\"showbuilds.cgi?tree=$form{'tree'}\">Return to the Build Page</a>
|
||||
<dt><a href=\"addnote.cgi?tree=$tree\&buildname=$enc_buildname\&buildtime=$buildtime\&logfile=$logfile\&errorparser=$errorparser\">
|
||||
Add a Comment to the Log</a>
|
||||
</font>
|
||||
";
|
||||
|
||||
#
|
||||
# Print notes
|
||||
#
|
||||
$found_note = 0;
|
||||
open(NOTES,"<$tree/notes.txt") || print "<h2>warning: Couldn't open $tree/notes.txt </h2>\n";
|
||||
while(<NOTES>){
|
||||
chop;
|
||||
($nbuildtime,$nbuildname,$nwho,$nnow,$nenc_note) = split(/\|/);
|
||||
#print "$_<br>\n";
|
||||
if( $nbuildtime == $buildtime && $nbuildname eq $buildname ){
|
||||
if( !$found_note ){
|
||||
print "<H2>Build Comments</H2>\n";
|
||||
$found_note = 1;
|
||||
}
|
||||
$now_str = &print_time($nnow);
|
||||
$note = &url_decode($nenc_note);
|
||||
print "<pre>\n[<b><a href=mailto:$nwho>$nwho</a> - $now_str</b>]\n$note\n</pre>";
|
||||
}
|
||||
}
|
||||
close(NOTES);
|
||||
|
||||
#
|
||||
# Print the summery fisrt
|
||||
#
|
||||
print "
|
||||
<H2>Build Error Summary</H2>
|
||||
<p> Click error to take you to the error in the log.
|
||||
<PRE>
|
||||
";
|
||||
$log_ln = 0;
|
||||
open( BUILD_IN, "$gzip -d -c $tree/$logfile|" );
|
||||
while( $line = <BUILD_IN> ){
|
||||
&output_summary_line( $line );
|
||||
}
|
||||
close( BUILD_IN );
|
||||
push @log_errors, 9999999;
|
||||
|
||||
print "</PRE>\n";
|
||||
|
||||
#
|
||||
# reset the error counter
|
||||
#
|
||||
$next_err = 0;
|
||||
|
||||
|
||||
print "<H2>Build Error Log</H2>\n<pre>";
|
||||
$log_ln = 0;
|
||||
open( BUILD_IN, "$gzip -d -c $tree/$logfile|" );
|
||||
while( $line = <BUILD_IN> ){
|
||||
&output_log_line( $line );
|
||||
}
|
||||
close( BUILD_IN );
|
||||
|
||||
|
||||
print
|
||||
"</PRE>
|
||||
|
||||
<p>
|
||||
<font size=+1><a name=\"err$next_err\">No More Errors</a></font>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
";
|
||||
|
||||
|
||||
sub output_summary_line {
|
||||
local( $line ) = @_;
|
||||
local( $has_error );
|
||||
|
||||
$has_error = &has_error( $line );
|
||||
|
||||
$line =~ s/&/&/g;
|
||||
$line =~ s/</</g;
|
||||
|
||||
if( $has_error ){
|
||||
push @log_errors, $log_ln + $LINES_AFTER_ERROR;
|
||||
if( ! $last_was_error ) {
|
||||
print "<a href=\"#err$next_err\">$line</a>";
|
||||
$next_err++;
|
||||
}
|
||||
$last_was_error = 1;
|
||||
}
|
||||
else {
|
||||
$last_was_error = 0;
|
||||
}
|
||||
|
||||
$log_ln++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
sub output_log_line {
|
||||
local( $line, $bSummary ) = @_;
|
||||
local( $has_error, $dur, $dur_min,$dur_sec, $dur_str, $logline );
|
||||
|
||||
$has_error = &has_error( $line );
|
||||
$has_warning = &has_warning( $line );
|
||||
|
||||
$line =~ s/&/&/g;
|
||||
$line =~ s/</</g;
|
||||
|
||||
$logline = '';
|
||||
|
||||
if( ($has_error || $has_warning) && &has_errorline( $line ) ) {
|
||||
$q = quotemeta( $error_file );
|
||||
#$goto_line = ($error_line ? 10 > $error_line - 10 : 1 );
|
||||
$goto_line = ($error_line > 10 ? $error_line - 10 : 1 );
|
||||
$cvsblame = ($error_guess ? "cvsguess.cgi" : "cvsblame.cgi");
|
||||
$line =~ s@$q@<a href=../bonsai/$cvsblame?file=$error_file_ref&rev=$cvs_branch&mark=$error_line#$goto_line $source_target>$error_file</a>@
|
||||
}
|
||||
|
||||
|
||||
if( $has_error ){
|
||||
if( ! $last_was_error ) {
|
||||
$logline .= "<a name=\"err$next_err\"></a>";
|
||||
$next_err++;
|
||||
$logline .= "<a href=\"#err$next_err\">NEXT</a> ";
|
||||
}
|
||||
else {
|
||||
$logline .= " ";
|
||||
}
|
||||
|
||||
$logline .= "<font color=\"000080\">$line</font>";
|
||||
|
||||
$last_was_error = 1;
|
||||
}
|
||||
elsif( $has_warning ){
|
||||
$logline .= " ";
|
||||
$logline .= "<font color=000080>$line</font>";
|
||||
}
|
||||
else {
|
||||
$logline .= " $line";
|
||||
$last_was_error = 0;
|
||||
}
|
||||
|
||||
&push_log_line( $logline );
|
||||
}
|
||||
|
||||
|
||||
sub push_log_line {
|
||||
local( $ln ) = @_;
|
||||
if( $fulltext ){
|
||||
print $ln;
|
||||
return;
|
||||
}
|
||||
|
||||
if( $log_ln > $log_errors[$cur_error] ){
|
||||
$cur_error++;
|
||||
}
|
||||
|
||||
if( $log_ln >= $log_errors[$cur_error] - $LINES_BEFORE_ERROR ){
|
||||
if( $log_skip != 0 ){
|
||||
print "\n<i><font size=+1> Skipping $log_skip Lines...</i></font>\n\n";
|
||||
$log_skip = 0;
|
||||
}
|
||||
print $ln;
|
||||
}
|
||||
else {
|
||||
$log_skip++;
|
||||
}
|
||||
$log_ln++;
|
||||
}
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 227 B |
Загрузка…
Ссылка в новой задаче