From 0d01ac7bc32226fb670a19b376a09de379485158 Mon Sep 17 00:00:00 2001 From: terry Date: Tue, 16 Jun 1998 21:43:24 +0000 Subject: [PATCH] Bonsai and Tinderbox have been freed. git-svn-id: svn://10.0.0.236/trunk@3931 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/webtools/bonsai/CGI.tcl | 128 +++ mozilla/webtools/bonsai/Makefile | 22 + mozilla/webtools/bonsai/README | 460 +++++++++ mozilla/webtools/bonsai/SourceChecker.cgi | 237 +++++ mozilla/webtools/bonsai/SourceChecker.pm | 192 ++++ mozilla/webtools/bonsai/addcheckin.tcl | 250 +++++ mozilla/webtools/bonsai/admin.cgi | 205 ++++ mozilla/webtools/bonsai/adminfuncs.tcl | 84 ++ mozilla/webtools/bonsai/adminmail.tcl | 66 ++ mozilla/webtools/bonsai/bonsai.gif | Bin 0 -> 20285 bytes mozilla/webtools/bonsai/branchspam.cgi | 91 ++ mozilla/webtools/bonsai/branchspammer.cgi | 100 ++ mozilla/webtools/bonsai/changebar.tcl | 83 ++ mozilla/webtools/bonsai/closemessage | 23 + mozilla/webtools/bonsai/contacthelp.html | 27 + mozilla/webtools/bonsai/countcheckins.cgi | 88 ++ mozilla/webtools/bonsai/createlegaldirs.tcl | 93 ++ mozilla/webtools/bonsai/cvsblame.cgi | 599 +++++++++++ mozilla/webtools/bonsai/cvsblame.pl | 816 +++++++++++++++ mozilla/webtools/bonsai/cvsguess.cgi | 72 ++ mozilla/webtools/bonsai/cvsindex.pl | 91 ++ mozilla/webtools/bonsai/cvslog.cgi | 493 +++++++++ mozilla/webtools/bonsai/cvsmenu.pl | 64 ++ mozilla/webtools/bonsai/cvsquery.cgi | 647 ++++++++++++ mozilla/webtools/bonsai/cvsquery.pl | 443 ++++++++ mozilla/webtools/bonsai/cvsqueryform.cgi | 321 ++++++ mozilla/webtools/bonsai/cvsregexp.html | 257 +++++ mozilla/webtools/bonsai/cvsview2.cgi | 963 ++++++++++++++++++ mozilla/webtools/bonsai/doadmin.cgi | 131 +++ mozilla/webtools/bonsai/doeditcheckin.cgi | 103 ++ mozilla/webtools/bonsai/doeditmessage.cgi | 74 ++ mozilla/webtools/bonsai/doeditprofile.cgi | 73 ++ mozilla/webtools/bonsai/doeditwhiteboard.cgi | 83 ++ mozilla/webtools/bonsai/dolog.pl | 220 ++++ mozilla/webtools/bonsai/dotweak.cgi | 121 +++ mozilla/webtools/bonsai/editcheckin.cgi | 91 ++ mozilla/webtools/bonsai/editmessage.cgi | 99 ++ mozilla/webtools/bonsai/editprofile.cgi | 109 ++ mozilla/webtools/bonsai/editwhiteboard.cgi | 45 + mozilla/webtools/bonsai/globals.tcl | 672 ++++++++++++ mozilla/webtools/bonsai/handleAdminMail.tcl | 32 + mozilla/webtools/bonsai/handleCheckinMail.tcl | 36 + mozilla/webtools/bonsai/header.pl | 61 ++ mozilla/webtools/bonsai/index.html | 12 + mozilla/webtools/bonsai/indextest.pl | 44 + mozilla/webtools/bonsai/lloydcgi.pl | 89 ++ mozilla/webtools/bonsai/localprofile.cgi | 79 ++ mozilla/webtools/bonsai/maketables.sh | 146 +++ mozilla/webtools/bonsai/moduleanalyse.cgi | 134 +++ mozilla/webtools/bonsai/modules.pl | 152 +++ mozilla/webtools/bonsai/multidiff.cgi | 129 +++ mozilla/webtools/bonsai/myglobrecur.tcl | 79 ++ mozilla/webtools/bonsai/openmessage | 35 + mozilla/webtools/bonsai/perlifyconfig.tcl | 83 ++ mozilla/webtools/bonsai/processqueue.pl | 35 + mozilla/webtools/bonsai/profile.cgi | 83 ++ mozilla/webtools/bonsai/rebuildcvshistory.cgi | 386 +++++++ mozilla/webtools/bonsai/rebuilddatabase.tcl | 196 ++++ mozilla/webtools/bonsai/rebuildtaginfo.cgi | 103 ++ mozilla/webtools/bonsai/repophook.cgi | 134 +++ mozilla/webtools/bonsai/reposfiles.pl | 58 ++ mozilla/webtools/bonsai/rview.cgi | 196 ++++ mozilla/webtools/bonsai/show2.cgi | 348 +++++++ mozilla/webtools/bonsai/showcheckins.cgi | 350 +++++++ mozilla/webtools/bonsai/switchtree.cgi | 54 + mozilla/webtools/bonsai/testlock.pl | 12 + mozilla/webtools/bonsai/toplevel.cgi | 261 +++++ mozilla/webtools/bonsai/trapdoor.c | 7 + mozilla/webtools/bonsai/utils.pl | 131 +++ mozilla/webtools/bonsai/viewold.cgi | 73 ++ mozilla/webtools/registry/file.cgi | 102 ++ mozilla/webtools/registry/lloydcgi.pl | 44 + mozilla/webtools/registry/who.cgi | 82 ++ mozilla/webtools/tinderbox/1afi003r.gif | Bin 0 -> 12967 bytes mozilla/webtools/tinderbox/Empty.html | 1 + mozilla/webtools/tinderbox/README | 73 ++ mozilla/webtools/tinderbox/addimage.cgi | 402 ++++++++ mozilla/webtools/tinderbox/addnote.cgi | 86 ++ mozilla/webtools/tinderbox/admintree.cgi | 114 +++ mozilla/webtools/tinderbox/buildwho.pl | 90 ++ mozilla/webtools/tinderbox/clean.pl | 32 + mozilla/webtools/tinderbox/copydata.pl | 91 ++ mozilla/webtools/tinderbox/doadmin.cgi | 174 ++++ mozilla/webtools/tinderbox/ep_mac.pl | 44 + mozilla/webtools/tinderbox/ep_unix.pl | 59 ++ mozilla/webtools/tinderbox/ep_windows.pl | 73 ++ mozilla/webtools/tinderbox/faq.html | 31 + mozilla/webtools/tinderbox/fixupimages.pl | 217 ++++ mozilla/webtools/tinderbox/globals.pl | 488 +++++++++ mozilla/webtools/tinderbox/handlemail.pl | 44 + mozilla/webtools/tinderbox/imagelog.pl | 43 + mozilla/webtools/tinderbox/index.html | 12 + mozilla/webtools/tinderbox/processbuild.pl | 214 ++++ mozilla/webtools/tinderbox/reledanim.gif | Bin 0 -> 1685 bytes mozilla/webtools/tinderbox/showbuilds.cgi | 552 ++++++++++ mozilla/webtools/tinderbox/showimages.cgi | 136 +++ mozilla/webtools/tinderbox/showlog.cgi | 282 +++++ mozilla/webtools/tinderbox/star.gif | Bin 0 -> 227 bytes 98 files changed, 15760 insertions(+) create mode 100755 mozilla/webtools/bonsai/CGI.tcl create mode 100755 mozilla/webtools/bonsai/Makefile create mode 100644 mozilla/webtools/bonsai/README create mode 100755 mozilla/webtools/bonsai/SourceChecker.cgi create mode 100755 mozilla/webtools/bonsai/SourceChecker.pm create mode 100755 mozilla/webtools/bonsai/addcheckin.tcl create mode 100755 mozilla/webtools/bonsai/admin.cgi create mode 100755 mozilla/webtools/bonsai/adminfuncs.tcl create mode 100755 mozilla/webtools/bonsai/adminmail.tcl create mode 100755 mozilla/webtools/bonsai/bonsai.gif create mode 100755 mozilla/webtools/bonsai/branchspam.cgi create mode 100755 mozilla/webtools/bonsai/branchspammer.cgi create mode 100755 mozilla/webtools/bonsai/changebar.tcl create mode 100644 mozilla/webtools/bonsai/closemessage create mode 100644 mozilla/webtools/bonsai/contacthelp.html create mode 100755 mozilla/webtools/bonsai/countcheckins.cgi create mode 100755 mozilla/webtools/bonsai/createlegaldirs.tcl create mode 100755 mozilla/webtools/bonsai/cvsblame.cgi create mode 100755 mozilla/webtools/bonsai/cvsblame.pl create mode 100755 mozilla/webtools/bonsai/cvsguess.cgi create mode 100755 mozilla/webtools/bonsai/cvsindex.pl create mode 100755 mozilla/webtools/bonsai/cvslog.cgi create mode 100644 mozilla/webtools/bonsai/cvsmenu.pl create mode 100755 mozilla/webtools/bonsai/cvsquery.cgi create mode 100755 mozilla/webtools/bonsai/cvsquery.pl create mode 100755 mozilla/webtools/bonsai/cvsqueryform.cgi create mode 100644 mozilla/webtools/bonsai/cvsregexp.html create mode 100755 mozilla/webtools/bonsai/cvsview2.cgi create mode 100755 mozilla/webtools/bonsai/doadmin.cgi create mode 100755 mozilla/webtools/bonsai/doeditcheckin.cgi create mode 100755 mozilla/webtools/bonsai/doeditmessage.cgi create mode 100755 mozilla/webtools/bonsai/doeditprofile.cgi create mode 100755 mozilla/webtools/bonsai/doeditwhiteboard.cgi create mode 100755 mozilla/webtools/bonsai/dolog.pl create mode 100755 mozilla/webtools/bonsai/dotweak.cgi create mode 100755 mozilla/webtools/bonsai/editcheckin.cgi create mode 100755 mozilla/webtools/bonsai/editmessage.cgi create mode 100755 mozilla/webtools/bonsai/editprofile.cgi create mode 100755 mozilla/webtools/bonsai/editwhiteboard.cgi create mode 100755 mozilla/webtools/bonsai/globals.tcl create mode 100755 mozilla/webtools/bonsai/handleAdminMail.tcl create mode 100755 mozilla/webtools/bonsai/handleCheckinMail.tcl create mode 100644 mozilla/webtools/bonsai/header.pl create mode 100644 mozilla/webtools/bonsai/index.html create mode 100755 mozilla/webtools/bonsai/indextest.pl create mode 100755 mozilla/webtools/bonsai/lloydcgi.pl create mode 100755 mozilla/webtools/bonsai/localprofile.cgi create mode 100755 mozilla/webtools/bonsai/maketables.sh create mode 100755 mozilla/webtools/bonsai/moduleanalyse.cgi create mode 100755 mozilla/webtools/bonsai/modules.pl create mode 100755 mozilla/webtools/bonsai/multidiff.cgi create mode 100644 mozilla/webtools/bonsai/myglobrecur.tcl create mode 100644 mozilla/webtools/bonsai/openmessage create mode 100755 mozilla/webtools/bonsai/perlifyconfig.tcl create mode 100755 mozilla/webtools/bonsai/processqueue.pl create mode 100755 mozilla/webtools/bonsai/profile.cgi create mode 100755 mozilla/webtools/bonsai/rebuildcvshistory.cgi create mode 100755 mozilla/webtools/bonsai/rebuilddatabase.tcl create mode 100755 mozilla/webtools/bonsai/rebuildtaginfo.cgi create mode 100755 mozilla/webtools/bonsai/repophook.cgi create mode 100755 mozilla/webtools/bonsai/reposfiles.pl create mode 100755 mozilla/webtools/bonsai/rview.cgi create mode 100755 mozilla/webtools/bonsai/show2.cgi create mode 100755 mozilla/webtools/bonsai/showcheckins.cgi create mode 100755 mozilla/webtools/bonsai/switchtree.cgi create mode 100755 mozilla/webtools/bonsai/testlock.pl create mode 100755 mozilla/webtools/bonsai/toplevel.cgi create mode 100644 mozilla/webtools/bonsai/trapdoor.c create mode 100644 mozilla/webtools/bonsai/utils.pl create mode 100755 mozilla/webtools/bonsai/viewold.cgi create mode 100755 mozilla/webtools/registry/file.cgi create mode 100755 mozilla/webtools/registry/lloydcgi.pl create mode 100755 mozilla/webtools/registry/who.cgi create mode 100644 mozilla/webtools/tinderbox/1afi003r.gif create mode 100644 mozilla/webtools/tinderbox/Empty.html create mode 100644 mozilla/webtools/tinderbox/README create mode 100755 mozilla/webtools/tinderbox/addimage.cgi create mode 100755 mozilla/webtools/tinderbox/addnote.cgi create mode 100755 mozilla/webtools/tinderbox/admintree.cgi create mode 100755 mozilla/webtools/tinderbox/buildwho.pl create mode 100755 mozilla/webtools/tinderbox/clean.pl create mode 100755 mozilla/webtools/tinderbox/copydata.pl create mode 100755 mozilla/webtools/tinderbox/doadmin.cgi create mode 100755 mozilla/webtools/tinderbox/ep_mac.pl create mode 100755 mozilla/webtools/tinderbox/ep_unix.pl create mode 100755 mozilla/webtools/tinderbox/ep_windows.pl create mode 100755 mozilla/webtools/tinderbox/faq.html create mode 100755 mozilla/webtools/tinderbox/fixupimages.pl create mode 100755 mozilla/webtools/tinderbox/globals.pl create mode 100755 mozilla/webtools/tinderbox/handlemail.pl create mode 100755 mozilla/webtools/tinderbox/imagelog.pl create mode 100755 mozilla/webtools/tinderbox/index.html create mode 100755 mozilla/webtools/tinderbox/processbuild.pl create mode 100644 mozilla/webtools/tinderbox/reledanim.gif create mode 100755 mozilla/webtools/tinderbox/showbuilds.cgi create mode 100755 mozilla/webtools/tinderbox/showimages.cgi create mode 100755 mozilla/webtools/tinderbox/showlog.cgi create mode 100644 mozilla/webtools/tinderbox/star.gif diff --git a/mozilla/webtools/bonsai/CGI.tcl b/mozilla/webtools/bonsai/CGI.tcl new file mode 100755 index 00000000000..f4f5fd00547 --- /dev/null +++ b/mozilla/webtools/bonsai/CGI.tcl @@ -0,0 +1,128 @@ +# -*- 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 + +# Takes something that was quoted for a URL line (%20 for spaces and stuff), +# and returns back the intended string. +proc url_decode {buf} { + regsub -all {\\(.)} $buf {\1} buf ; regsub -all {\\} $buf {\\\\} buf ; + regsub -all { } $buf {\ } buf ; regsub -all {\+} $buf {\ } buf ; + regsub -all {\$} $buf {\$} buf ; regsub -all \n $buf {\n} buf ; + regsub -all {;} $buf {\;} buf ; regsub -all {\[} $buf {\[} buf ; + regsub -all \" $buf \\\" buf ; regsub ^\{ $buf \\\{ buf ; + regsub -all -nocase {%([a-fA-F0-9][a-fA-F0-9])} $buf {[format %c 0x\1]} buf + regsub -all "\r\n" $buf "\n" buf + regsub -all "\r" $buf "\n" buf + eval return \"$buf\" +} + +proc lookup { a key } { + global $a + set ref [format %s(%s) $a $key] + if { [ info exists $ref] } { + eval return \$$ref + } else { + return "" + } +} + +proc FormData { field } { + global FORM + return [join $FORM($field)] +} + +proc ProcessFormFields {buffer} { + global FORM treeid + catch {unset FORM} + foreach item [ split $buffer & ] { + set el [ split $item = ] + set value [url_decode [lindex $el 1]] + set name [lindex $el 0] + if { $value != "" } { + lappend FORM($name) $value + } else { + set isnull($name) 1 + } + } + if {[info exists isnull]} { + foreach name [array names isnull] { + if {![info exists FORM($name)]} { + set FORM($name) "" + } + } + } + if {[info exists FORM(treeid)]} { + set treeid $FORM(treeid) + } + if {[info exists FORM(batchid)]} { + global batchid readonly + source [DataDir]/batchid + if {$batchid != $FORM(batchid)} { + set batchid $FORM(batchid) + set readonly 1 + } + } +} + + +proc BatchIdPart {{initstr ""}} { + global treeid batchid readonly + set result "" + if {![cequal $treeid "default"] || $readonly} { + set result $initstr + } + if {![cequal $treeid "default"]} { + append result "&treeid=$treeid" + } + if {$readonly} { + append result "&batchid=$batchid" + } + return $result +} + + +if { [info exists env(REQUEST_METHOD) ] } { + if { $env(REQUEST_METHOD) == "GET" } { + set buffer [lookup env QUERY_STRING] + } else { set buffer [ read stdin $env(CONTENT_LENGTH) ] } + ProcessFormFields $buffer +} + +proc value_quote {var} { + regsub -all {&} "$var" {\&} var + regsub -all {"} "$var" {\"} var + regsub -all {<} "$var" {\<} var + regsub -all {>} "$var" {\>} var + return $var +} + +foreach pair [ split [lookup env HTTP_COOKIE] ";" ] { + set pair [string trim $pair] + set eq [string first = $pair ] + if {$eq == -1} { + set COOKIE($pair) "" + } else { + set COOKIE([string range $pair 0 [expr $eq - 1]]) [string range $pair [expr $eq + 1] end] + } +} + + +proc PutsTrailer {} { + puts "
Back to the top of Bonsai" +} diff --git a/mozilla/webtools/bonsai/Makefile b/mozilla/webtools/bonsai/Makefile new file mode 100755 index 00000000000..2933f1d51e6 --- /dev/null +++ b/mozilla/webtools/bonsai/Makefile @@ -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 diff --git a/mozilla/webtools/bonsai/README b/mozilla/webtools/bonsai/README new file mode 100644 index 00000000000..3fab2b12161 --- /dev/null +++ b/mozilla/webtools/bonsai/README @@ -0,0 +1,460 @@ +This is Bonsai. See . + + + ================================= + 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= treeid= + command=[open|close] + closetimestamp= + lastgood= + doclear= + + doadmin.cgi password= treeid= + command=tweaktimes + lastgood= + lastclose= + + doadmin.cgi password= treeid= + command=editmotd + origmotd= + motd= + + editmessage.cgi treeid= + msgname=[openmessage|closemessage| + treeopened|treeopenedsamehook| + treeclosed] + #### note: no password? + + repophook.cgi password= treeid= + command=repophook + startfrom= + + rebuildtaginfo.cgi password= + treeid= + command=rebuildtaginfo + + rebuildcvshistory.cgi password= + treeid= + command=rebuildcvs + startfrom= + firstfile= + subdir= + + doadmin.cgi password= treeid= + command=changepassword + password= + newpassword= + newpassword2= + doglobal= + +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= + file= + who= + 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= diff --git a/mozilla/webtools/bonsai/SourceChecker.cgi b/mozilla/webtools/bonsai/SourceChecker.cgi new file mode 100755 index 00000000000..0cac292f155 --- /dev/null +++ b/mozilla/webtools/bonsai/SourceChecker.cgi @@ -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 , 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'; +

SourceChecker Dictionary Maintainance

+END_OF_HEADER + } + + +sub print_page_trailer() + { + print <<'END_OF_TRAILER'; +
+ +Last updated 5 Feb 1998. +Dictionary maintainance and help. +Mail feedback to <scc@netscape.com>. +END_OF_TRAILER + } + + + +$error_header = '

I couldn\'t process your request...

'; + +sub print_error($) + { + local $message = shift; + print "$error_header

Error: $message

"; + $error_header = ''; + } + + +sub print_query_building_form() + { + print $query->start_multipart_form; + + print '

Build a new request

'; + print '

...to modify or create a remote dictionary with words from one or more local files.

'; + + print '

Files on the server

'; + print '

...i.e., the dictionary to be created or modified.

'; + + print $query->textfield( -name=>'dictionary', + -default=>'', + -override=>1, + -size=>30 ); + print '-- the path to dictionary.'; + + print '

Files on your local machine

'; + print '

...that will be uploaded to the server, so their contents can be added to the dictionary.

'; + + print '
'; + print $query->filefield( -name=>'ignore_english', -size=>30 ); + print '-- contains english (i.e., transformable) words to ignore.'; + + print '
'; + print $query->filefield( -name=>'ignore_strings', -size=>30 ); + print '-- contains identifiers (i.e., non-transformable) words to ignore.'; + + print '
'; + print $query->filefield( -name=>'flag_strings', -size=>30 ); + print '-- contains identifiers words to be flagged.'; + + print '
'; + print $query->filefield( -name=>'ignore_names', -size=>30 ); + print '-- contains user names to be ignored.'; + + print '
'; + 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__ + diff --git a/mozilla/webtools/bonsai/SourceChecker.pm b/mozilla/webtools/bonsai/SourceChecker.pm new file mode 100755 index 00000000000..0bb7d4fc0e0 --- /dev/null +++ b/mozilla/webtools/bonsai/SourceChecker.pm @@ -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 = ('', '', ''); +@markup_suffix = ('', '', ''); + + + +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; + + 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; diff --git a/mozilla/webtools/bonsai/addcheckin.tcl b/mozilla/webtools/bonsai/addcheckin.tcl new file mode 100755 index 00000000000..2e1adea161d --- /dev/null +++ b/mozilla/webtools/bonsai/addcheckin.tcl @@ -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 diff --git a/mozilla/webtools/bonsai/admin.cgi b/mozilla/webtools/bonsai/admin.cgi new file mode 100755 index 00000000000..fd4afd20420 --- /dev/null +++ b/mozilla/webtools/bonsai/admin.cgi @@ -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 + + + + +Bonsai administration + + + +

Bonsai administration

+ +You realize, of course, that you have to know the magic password to do +anything from here. + +
+Go tweak bunches of checkins at once. +
+ +" + + +puts " +
+Password:
+ +" + +if {$treeopen} { + puts " + +Closing time stamp is: +
+ +" +} else { + puts " + +The new \"good\" timestamp is: + +
+Clear the list of checkins.
+ +" +} +puts " +
+ +
+ +
+Password:
+ + + + + + + + + + + +
Last good timestamp:
Last close timestamp:
+ +
+ + +
+ +
+ +Password:
+ + +Change the message-of-the-day:
+ +
+ +
+ + +
+ +
+ + +Change the e-mail message sent: + +
+ + +
+ + +
+ +
+ +Password:
+ +Repopulate the hook from scratch.

+This can be very dangerous. You should +usually only need to do this to populate a new Bonsai branch. +

+Use any checkin since: + +
+ +

+ +
+ +
+ +Password:
+ +Recreate the entire table of tags for the $treeinfo($treeid,repository) +repository from scratch. +

+This can take a very, very long time. 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.) +
+ +

+ +
+ +
+ +Password:
+ +Recreate the entire list of every checkin ever done to the +$treeinfo($treeid,repository) repository from scratch. +

+This can take an incredibly long time. You +should +usually only need to do this when first introducing an entire CVS repository +into Bonsai. +

+Ignore checkins earlier than: + +
+Ignore files before (must be full path starting with $treeinfo($treeid,repository); leave blank to do everything): + +
+Only do files within the subdirectory of $treeinfo($treeid,repository) named: + +
+ +

+ +
+
+ + +Change password.
+Old password:
+New password:
+Retype new password:
+Change password for this tree
+Change master Bonsai password
+ +
+" + + +PutsTrailer + +exit diff --git a/mozilla/webtools/bonsai/adminfuncs.tcl b/mozilla/webtools/bonsai/adminfuncs.tcl new file mode 100755 index 00000000000..3a62a22e707 --- /dev/null +++ b/mozilla/webtools/bonsai/adminfuncs.tcl @@ -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 +} diff --git a/mozilla/webtools/bonsai/adminmail.tcl b/mozilla/webtools/bonsai/adminmail.tcl new file mode 100755 index 00000000000..00d0d1f6bce --- /dev/null +++ b/mozilla/webtools/bonsai/adminmail.tcl @@ -0,0 +1,66 @@ +#!/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 +source adminfuncs.tcl + +proc GetDate {line} { + set date [getclock] + if [regexp -- {[0-9].*$} $line str] { + catch {set date [convertclock $str]} + } + return $date +} + + + +Lock + +for_file line $argv { + if {[scan $line "%s %s" foobar theTree] != 2} { + continue + } + set treeid $theTree + switch -glob -- $foobar { + OPENNOCLEAR - + opennoclear { + LoadCheckins + AdminOpenTree [GetDate $line] 0 + WriteCheckins + } + OPEN - + open { + LoadCheckins + AdminOpenTree [GetDate $line] 1 + WriteCheckins + } + CLOSE - + close { + LoadCheckins + AdminCloseTree [GetDate $line] + WriteCheckins + } + } +} + +Unlock + +exit 0 + + diff --git a/mozilla/webtools/bonsai/bonsai.gif b/mozilla/webtools/bonsai/bonsai.gif new file mode 100755 index 0000000000000000000000000000000000000000..5ae282f5b38fa74dc086e72e1d6716c50399ae5b GIT binary patch literal 20285 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 literal 0 HcmV?d00001 diff --git a/mozilla/webtools/bonsai/branchspam.cgi b/mozilla/webtools/bonsai/branchspam.cgi new file mode 100755 index 00000000000..00ed021717d --- /dev/null +++ b/mozilla/webtools/bonsai/branchspam.cgi @@ -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 + +"; + +require 'modules.pl'; + + +print " + +The CVS Branch Spammer (TM) + +

The CVS Branch Spammer (TM)

+

Questions, Comments, Feature requests? mail ltabb +

What this tool does

+ +

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. + +

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. + +

To run this program answer the following questions and bonk the spam button. + + +

+

+"; + + +# +# module selector +# +print " + +Pick the name of the CVS Module you use to pull your source +\n"; + +# +# Branch +# +print "
What is the name of your branch: \n"; + +print "
Who should the email message be from?: \n"; + +print " +
+
+ +
"; + diff --git a/mozilla/webtools/bonsai/branchspammer.cgi b/mozilla/webtools/bonsai/branchspammer.cgi new file mode 100755 index 00000000000..73dfff2e5a6 --- /dev/null +++ b/mozilla/webtools/bonsai/branchspammer.cgi @@ -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 + +"; + +$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 "

Running Query, this may take a while...

"; + +$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 "
";
+for $ci (@$result) {
+    $ci->[$CI_LOG] = '';
+    $s = join("|",@$ci);
+    print "$s\n";
+}
+
diff --git a/mozilla/webtools/bonsai/changebar.tcl b/mozilla/webtools/bonsai/changebar.tcl
new file mode 100755
index 00000000000..a50d775de92
--- /dev/null
+++ b/mozilla/webtools/bonsai/changebar.tcl
@@ -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.
+
+# Takes two files, and creates a file with changebars.
+
+set file1 [lvarpop argv]
+set file2 [lvarpop argv]
+
+set data(foo) {}
+unset data(foo)
+
+set count 0
+for_file line $file1 {
+    incr count
+    set data($count) $line
+    set mark($count) " "
+}
+
+set fid [open "|/usr/local/bin/diff -b -e $file1 $file2" "r"]
+
+
+proc Delete {first last} {
+    global data
+    for {set i $first} {$i<=$last} {incr i} {
+        unset data($i)
+    }
+}
+
+proc Add {first fid} {
+    global data mark
+    set sub 10000
+    while {[gets $fid line] >= 0} {
+        if {[cequal $line "."]} {
+            break
+        }
+        set data($first.$sub) $line
+        set mark($first.$sub) "|"
+        incr sub
+    }
+}
+
+
+
+while {[gets $fid line] >= 0} {
+    if {![regexp {^(.*),(.*)(a|c|d)$} $line foo first last]} {
+        set first [crange $line 0 end-1]
+        set last $first
+    }
+    switch [cindex $line end] {
+        d {
+            Delete $first $last
+        }
+        c {
+            Delete $first $last
+            Add $first $fid
+        }
+        a {
+            Add $first $fid
+        }
+    }
+}
+
+catch {close $fid}
+
+foreach i [lsort -real [array names data]] {
+    puts "$mark($i) $data($i)"
+}
diff --git a/mozilla/webtools/bonsai/closemessage b/mozilla/webtools/bonsai/closemessage
new file mode 100644
index 00000000000..997eb53b7fc
--- /dev/null
+++ b/mozilla/webtools/bonsai/closemessage
@@ -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
+
+
+
+

Boy, you better have had permission!

+ +You just checked into %dir% the files %files%. 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. + +

+ +Your contact info and other vital data is listed below. Please +update +this info immediately if it is at all inaccurate or incorrect. + +


+ +%profile% diff --git a/mozilla/webtools/bonsai/contacthelp.html b/mozilla/webtools/bonsai/contacthelp.html new file mode 100644 index 00000000000..7c3574c50a5 --- /dev/null +++ b/mozilla/webtools/bonsai/contacthelp.html @@ -0,0 +1,27 @@ + +Changing other people's contact info. + + + +

Changing other people's contact info.

+ +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. +

+Note that you're only allowed to change the "Current Contact Info" +field this way. It won't let you change anything else. + +


+ +Back to the top of Bonsai + +
+
Terry Weissman <terry@netscape.com>
+ +Last modified: Wed Oct 30 13:03:35 1996 + + diff --git a/mozilla/webtools/bonsai/countcheckins.cgi b/mozilla/webtools/bonsai/countcheckins.cgi new file mode 100755 index 00000000000..84273a42d31 --- /dev/null +++ b/mozilla/webtools/bonsai/countcheckins.cgi @@ -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 + + +Beancounter central. + +

Meaningless checkin statistics

+ + + + + + +" + +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 "" + puts "" + puts "" + puts "" + puts "" + puts "" +} +puts "
Tree closedNumber
of
people
making
changes
Number of checkins
$donetime($i)$numpeople($i)$num($i)
 
" + +PutsTrailer + +exit diff --git a/mozilla/webtools/bonsai/createlegaldirs.tcl b/mozilla/webtools/bonsai/createlegaldirs.tcl new file mode 100755 index 00000000000..d850e6254e5 --- /dev/null +++ b/mozilla/webtools/bonsai/createlegaldirs.tcl @@ -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 diff --git a/mozilla/webtools/bonsai/cvsblame.cgi b/mozilla/webtools/bonsai/cvsblame.cgi new file mode 100755 index 00000000000..7f13ae0cdf6 --- /dev/null +++ b/mozilla/webtools/bonsai/cvsblame.cgi @@ -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 , 12-Sep-97. +# Modified: Marc Byrd , 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.

\n"; + print "\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.

\n"; +print "\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 = "
";
+} else {
+    # We don't want your stinking Windows font
+    #$font_tag = "";
+    $font_tag = "
";
+}
+
+# Print link at top for directory browsing
+#
+$output = "
"; +foreach $path (split('/',$rcs_path)) { + $link_path .= $path; + $output .= "$path/ "; + $link_path .= '/'; +} +$output .= "$file_tail " + ." ("; +$output .= "$browse_revtag:" unless $browse_revtag eq 'HEAD'; +$output .= $revision if $revision; +$output .= ")"; + +$output .= "
"; +EmitHtmlHeader("CVS Blame", $output); +print "
\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; + } + # Add a link to traverse to included files + $text = &link_includes($text) if $opt_includes; + + + $output = ""; + + # Highlight lines + if (defined($mark_cmd = $mark_line{$line}) + && $mark_cmd ne 'end') { + + $output .= ""; + #if( defined($prev_revision{$file_rev})) { + $output .= ""; + #} + $output .= "
$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 .= "$revision "; + $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 .= "Previous Revision ($prev_revision{$file_rev}) 
"; + } + + print $output; +} +print "
\n"; + +# Write out cvs log messages as a JS variables +# +print ""; + +&print_bottom; + +print "
(This page is much cooler with a layers enabled browser)
"; + +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__; + + +CVS Blame $title_text + + + + +__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 off.'; + $new_linenum = 'on'; + } else { + $linenum_message = 'Line numbers are currently on.'; + $new_linenum = 'off'; + } + $src_roots_list = join('
', @src_roots); + + print <<__USAGE__; + + +CVS Blame $title_text + +

CVS Blame Usage

+Add parameters to the query string to view a file. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParamDefaultExampleDescription
file--ns/cmd/Makefilepath to file name
root$src_roots_list/warp/webrootcvs root
revHEAD1.3 +
ACTRA_branch
revision
line_numsoff *on +
off
line numbers
#<line_number>--#111jump to a line
+ +

Examples: +
  + + cvsblame.cgi?file=ns/cmd/Makefile +
  + + cvsblame.cgi?file=ns/cmd/xfe/mozilla.c&rev=Dogbert4xEscalation_BRANCH +
  + + cvsblame.cgi?file=projects/bonsai/cvsblame.cgi&root=/warp/webroot +
  + + cvsblame.cgi?file=ns/config/config.mk&line_nums=on +
  + + cvsblame.cgi?file=ns/cmd/xfe/dialogs.c#2384 +
+ +

+You may also begin a query with the CVS Query Form. +

+ + + + + + + + +
*Instead of the line_nums parameter, you can + + line numbers.
$linenum_message
+ + +
+__USAGE__ + &print_bottom; +} # sub print_usage + +sub print_bottom { + print <<__BOTTOM__; +
+ +Page configuration and help. +Mail feedback to <slamm\@netscape.com>. + + +__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\"$3\";$'"; + 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; + $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; + } + $text = $newtext . $oldtext; + + # Now fix the breakage of stuff on xfe. -byrd + if ($text =~ /(.*)<(.*@.*)>(.*\n)/) { + $text = $1 . "$2" . $3; + } + + return $text; +} diff --git a/mozilla/webtools/bonsai/cvsblame.pl b/mozilla/webtools/bonsai/cvsblame.pl new file mode 100755 index 00000000000..c731dcb8a40 --- /dev/null +++ b/mozilla/webtools/bonsai/cvsblame.pl @@ -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 = ; + $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 = ; + } + + # 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 "
revision = $revision\n";
+            print "date     = $date\n";
+            print "author   = $author\n";
+            print "branches = $branches\n";
+            print "next     = $next
\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 "
Keys:\n\n";
+        for $i (keys %tag_revision ){
+            $k = $tag_revision{$i};
+            print "yoyuo $i: $k\n";            
+        }
+        print "
\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() { + 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 = ; + 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 Specify CVS revision of file to display\n", +" 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); + } +} diff --git a/mozilla/webtools/bonsai/cvsguess.cgi b/mozilla/webtools/bonsai/cvsguess.cgi new file mode 100755 index 00000000000..bce58a5aa83 --- /dev/null +++ b/mozilla/webtools/bonsai/cvsguess.cgi @@ -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 "
$qstring
\n"; +} + +$query = $db->Query($qstring) || die $Mysql::db_errstr; + +while(@row = $query->fetchrow){ + $d = $row[0]; + push @fl, "$d/$file"; +} + +if( @fl == 0 ){ + print "

No files matched this file name. It may have been added recently.

"; +} +elsif( @fl == 1 ){ + $s = $fl[0]; + print " + + + "; +} +else { + print "

Pick the file that best matches the one you are looking for:

\n"; + for $s (@fl) { + print "
$s"; + } +} diff --git a/mozilla/webtools/bonsai/cvsindex.pl b/mozilla/webtools/bonsai/cvsindex.pl new file mode 100755 index 00000000000..f9628cfd16f --- /dev/null +++ b/mozilla/webtools/bonsai/cvsindex.pl @@ -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( ){ + if( /^LOGCOMMENT/ ){ + $done = 0; + $file_pos += length; + while( !$done && ($line = ) ){ + 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(); +} diff --git a/mozilla/webtools/bonsai/cvslog.cgi b/mozilla/webtools/bonsai/cvslog.cgi new file mode 100755 index 00000000000..9f1c43611a2 --- /dev/null +++ b/mozilla/webtools/bonsai/cvslog.cgi @@ -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 , 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.

\n"; + print "\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.

\n"; +print "\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 = ""; +} else { + # We don't want your stinking Windows font + $font_tag = ""; +} + +# Print link at top for directory browsing +# +$output = "
"; + +foreach $path (split('/',$rcs_path)) { + $link_path .= $path; + $output .= "$path/ "; + $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 = ""; +if ($opt_sort eq 'author') { + $table_header_tag .= "
RevAuthorDateLog"; +} else { + $table_header_tag .= "RevAuthorDateLog"; +} + +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; + eval ('$log =~ s@\d{4,6}@' . $BUGSYSTEMEXPR . '@g;'); + $log =~ s/\n|\r|\r\n/
/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 .= "
\n$table_tag"; + $row_count = 0; + } + + $output .= "" + ."'; + + $output .= "".$author + .' ' x ($max_author_length - length($author)).''; + $rev_time = $revision_ctime{$revision}; +# $rev_time =~ s/(19\d\d) (.\d:\d\d)/$1
$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 = "\"$rev_time\""; + } 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 = "$rev_time"; + } + + $output .= "$rev_time"; + $output .= " $log"; + + $output .= "\n"; + + print $output; +} +print ""; +&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__; + + +CVS Log $title_text + + + + + + + +__TOP__ +} # print_top + +sub print_usage { + local ($linenum_message) = ''; + local ($new_linenum, $src_roots_list); + local ($title_text) = "Usage"; + + $src_roots_list = join('
', @src_roots); + + print <<__USAGE__; + + +CVS Log $title_text + +

CVS Log Usage

+Add parameters to the query string to view a file. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParamDefaultExampleDescription
file--ns/cmd/MakefilePath to file name
root$src_roots_list/warp/webrootCVS root
revHEAD1.3 +
ACTRA_branch
Revision
author--slamm,mtoyFilter out these authors
#<rev_number>--#1.2Jump to a revision
+ +

Examples: +
  + + cvslog.cgi?file=ns/cmd/Makefile +
  + + cvslog.cgi?file=ns/cmd/xfe/mozilla.c&rev=Dogbert4xEscalation_BRANCH +
  + + cvslog.cgi?file=projects/bonsai/cvslog.cgi&root=/warp/webroot +
  + + cvslog.cgi?file=ns/cmd/xfe/dialogs.c#1.19 +
+

+You may also begin a query with the CVS Query Form. +

+__USAGE__ + &print_bottom; +} # sub print_usage + +sub print_bottom { + print <<__BOTTOM__; +
+ +Page configuration and help. +Mail feedback to <slamm\@netscape.com>. + + +__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 "
+ + + + +
+ + + + + + + + + + + + + +
lxr: browse the source code as hypertext.
diff: compare any two versions.
blame: annotate the author of each line.
+
+
+"; +} diff --git a/mozilla/webtools/bonsai/cvsmenu.pl b/mozilla/webtools/bonsai/cvsmenu.pl new file mode 100644 index 00000000000..6f8057df577 --- /dev/null +++ b/mozilla/webtools/bonsai/cvsmenu.pl @@ -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 " +
Menu
+

"; + +my $pass; +my $i; +foreach $pass ("cvsqueryform|Query", + "rview|Browse", + "moduleanalyse|Examine Modules") { + ($page, $title) = split(/\|/, $pass); + print "$title
    \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 "
  • {'repository'}&module=$treeinfo{$i}->{'module'}$branch>$desc\n"; + }; + print "
\n"; +}; + +if (open(EXTRA, ") { + print $_; + } + close EXTRA; +} + +print "
+

Questions, Comments, Feature requests? mail terry +
+"; + +} + diff --git a/mozilla/webtools/bonsai/cvsquery.cgi b/mozilla/webtools/bonsai/cvsquery.cgi new file mode 100755 index 00000000000..f1ccf3b5e28 --- /dev/null +++ b/mozilla/webtools/bonsai/cvsquery.cgi @@ -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 = ""; + +print "Content-type: text/html + +"; + +$script_str=''; +&setup_script; + +print "$script_str"; + +#print "
";
+
+
+$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 = "
+

$e +

+Modify Query +
Mail everyone on this page +($pCount people) +"; + +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 "

";
+    for $ci (@$result) {
+        $ci->[$CI_LOG] = '';
+        $s = join("|",@$ci);
+        print "$s\n";
+    }
+}
+
+
+#
+# code to debug the modules_map
+#
+#print "
\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 "\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 "\n";
+
+    print "\n";
+}
+
+sub print_head {
+
+if ($versioninfo ne "") {
+    print "";
+    print "";
+    print "";
+    print "";
+    print "";
+    print "(+$lines_added/$lines_removed) Lines changed.";
+}
+
+$anchor = $ENV{QUERY_STRING};
+$anchor =~ s/\&sortby\=[A-Za-z\ \+]*//g;
+$anchor = "
+
+
+";
+}
+
+
+sub print_foot {
+    print "
${sm_font_tag}$t"; + print "[$CI_WHO]','',event);\" >" + . "$ci->[$CI_WHO]\n"; + print "[$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\/
  /; +# # Insert a
before any directory named +# # 'classes.' +# } +# print " $d/
  $ci->[$CI_FILE]
\n"; +# } +# else{ +# print " $ci->[$CI_DIR]/$ci->[$CI_FILE]\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 "
${sm_font_tag}$rev\n"; + } + else { + print "\ \n"; + } + + if( !$query_branch_head ){ + print "$ci->[$CI_BRANCH] \n"; + } + print "${sm_font_tag}$ci->[$CI_LINES_ADDED]/$ci->[$CI_LINES_REMOVED] \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$2<\/a>$3/g; + # Makes numbers into links to bugsplat. + + $log =~ s/\n/
/g; + # Makes newlines into
's + + if( $span > 1 ){ + print "
$log\n"; + } + else { + print "$log\n"; + } + } + print "
$anchor>When +${anchor}&sortby=Who>Who +${anchor}&sortby=File>File +Rev +"; + +$descwidth = 47; +if( !$query_branch_head ){ + print "Branch\n"; + $descwidth -= 2; +} + +print " +${anchor}&sortby=Change+Size>+/- +Description +
"; + print "

"; +} + +sub html_log { + local( $log ) = @_; + $log =~ s/&/&/g; + $log =~ s/ 7000000) { + return $d; + } + return 0; +} + + + +sub setup_script { + +$script_str =<<'ENDJS'; + + + + + +ENDJS + +} + +# +# Actually do the query +# +sub query_to_english { + my $english = 'Checkins '; + + if( $query_module eq 'allrepositories' ){ + $english .= "to All Repositories "; + } + elsif( $query_module ne 'all' && @query_dirs == 0 ){ + $english .= "to module $query_module "; + } + elsif( $form{dir} ne "" ) { + my $word = "directory"; + if (@query_dirs > 1) { + $word = "directories"; + } + $english .= "to $word $form{dir} "; + } + + 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 $query_branch "; + } + } + + 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 $t "; + } + + 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 $t "; + } + } + return $english . ":"; +} + diff --git a/mozilla/webtools/bonsai/cvsquery.pl b/mozilla/webtools/bonsai/cvsquery.pl new file mode 100755 index 00000000000..454f70139eb --- /dev/null +++ b/mozilla/webtools/bonsai/cvsquery.pl @@ -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 "
 Query: $qstring
"; + } + + $query = $db->Query($qstring) || die $Mysql::db_errstr; + + $lastlog = 0; + while(@row = $query->fetchrow) { + $ci = []; +# print "
";
+        for ($i=0 ; $i<=$CI_LOG ; $i++) {
+            $ci->[$i] = $row[$i];
+# print "$row[$i] ";
+        }
+# print "
"; + + + 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 "
$key begintag is $rev
\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 "
$key endtag is $rev
\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 "
parsing tag $tagname
\n"; + while ( ) { + 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 "
Added ($file,$version) for tag $tagname
\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 "

Please wait -- rebuilding index file...

\n"; + system "./cvsindex.pl $CVS_ROOT"; + print "

...OK, done.

\n"; + } + Lock(); + if(! open(IDX , "<$CHECKIN_INDEX_FILE") ){ + print "

can't open index

"; + Unlock(); + return 0; + } + $i = 0; + while( ($line = ) && !$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 = ) ){ + 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; +} + + diff --git a/mozilla/webtools/bonsai/cvsqueryform.cgi b/mozilla/webtools/bonsai/cvsqueryform.cgi new file mode 100755 index 00000000000..6a6a2ae81b2 --- /dev/null +++ b/mozilla/webtools/bonsai/cvsqueryform.cgi @@ -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 " +

+

+

+ +"; + + +# +# module selector +# +print " + +\n"; +print ""; + +# +# Branch +# +if( defined $form{branch} ){ + $b = $form{branch}; +} +else { + $b = "HEAD"; +} +print " + +"; + +# +# Query by directory +# +print " + + + + +"; + +print " + + + + +"; + + +# +# Who +# +print " + + + +"; + + +# +# Log contains +# +#print " +#
+#Log contains: +#(you can use regular expressions)\n"; + + +# +# Sort order +# +print " + + + + +"; + +# +# 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 " + + + +"; + +print " + + + + +
Module: +"; +cvsmenu(); +print "
Branch:
\n" . +regexpradio('branchtype') . + "
(leaving this field empty will show you checkins on both +HEAD and branches) +
Directory: +
+(you can list multiple directories) +
File: +
" . +regexpradio('filetype') . " +
Who:
" . +regexpradio('whotype') . " +
Sort By: + +

Date:
+ + + + + + + + + + + + + + + + + + + + +
In the last hours
In the last day
In the last week
In the last month
Since the beginning of time (which happens to be $startdate currently)
+ + + + + + + +
+Between You can use the form +mm/dd/yy hh:mm:ss or a Unix time_t +(seconds since the Epoch.) +
+ and
+
+

+ + +
+

"; + +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 " +Exact match +      +Regular expression"; +} + + +sub fetchCachedStartDate { + my ($repository) = @_; + open(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, ") { + 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"; +} diff --git a/mozilla/webtools/bonsai/cvsregexp.html b/mozilla/webtools/bonsai/cvsregexp.html new file mode 100644 index 00000000000..b9d777f0ccc --- /dev/null +++ b/mozilla/webtools/bonsai/cvsregexp.html @@ -0,0 +1,257 @@ + + + + + + Regular expressions in the cvs query tool + + + +

+Description of MySQL regular expression syntax.

+Regular expressions are a powerful way of specifying complex searches. + +

MySQL uses regular Henry Spencers inplementation of regular expressions. +And that is aimed to conform to POSIX 1003.2. MySQL uses the extended +version. + +

To get more exact information see Henry Spencers regex.7 manual. + +

This is a simplistic reference that skips the details. From here on +a regualr expressions is called a regexp. + +

A regular expression describes a set of strings. The simplest case is +one that has no special characters in it. For example the regexp hello +matches hello and nothing else. + +

Nontrivial regular expressions use certain special constructs so that +they can match more than one string. For example, the regexp hello|word +matches either the string hello or the string word. + +

And a more comples example regexp B[an]*s matches any of the +strings Bananas, Baaaaas, Bs and all other string +starting with a B and continuing with any number of a +n and ending with a s. + +

The following special characters/constructs are known. +

+
+^
+ +
+Start of whole string.
+ +
mysql> select "fo\nfo" regexp "^fo$";           -> 0
+mysql> select "fofo" regexp "^fo";              -> 1
+ +
+$
+ +
+End of whole string.
+ +
mysql> select "fo\no" regexp "^fo\no$";         -> 1
+mysql> select "fo\no" regexp "^fo$";            -> 0
+ +
+.
+ +
+Any character (including newline).
+ +
mysql> select "fofo" regexp "^f.*";             -> 1
+mysql> select "fo\nfo" regexp "^f.*";           -> 1
+ +
+a*
+ +
+Any sequence of zero or more a's.
+ +
mysql> select "Ban" regexp "^Ba*n";             -> 1
+mysql> select "Baaan" regexp "^Ba*n";           -> 1
+mysql> select "Bn" regexp "^Ba*n";              -> 1
+ +
+a+
+ +
+Any sequence of one or more a's.
+ +
mysql> select "Ban" regexp "^Ba+n";             -> 1
+mysql> select "Bn" regexp "^Ba+n";              -> 0
+ +
+a?
+ +
+Either zero or one a.
+ +
mysql> select "Bn" regexp "^Ba?n";              -> 1
+mysql> select "Ban" regexp "^Ba?n";             -> 1
+mysql> select "Baan" regexp "^Ba?n";            -> 0
+ +
+de|abc
+ +
+Either the sequence de or abc.
+ +
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
+ +
+(abc)*
+ +
+Zero or more times the sequence abc.
+ +
mysql> select "pi" regexp "^(pi)+$";            -> 1
+mysql> select "pip" regexp "^(pi)+$";           -> 0
+mysql> select "pipi" regexp "^(pi)+$";          -> 1
+ +
+{1}
+ +
+{2,3}
+ +
+The is a more general way of writing regexps that match many occurences.
+ +
+
+a*
+ +
+Can be written as a{0,}.
+ +
++
+ +
+Can be written as a{1,}.
+ +
+?
+ +
+Can be written as a{0,1}.
+
+To be more precice an atom followed by a bound containing one integer i +and no comma matches a sequence of exactly i matches of the atom. +An atom followed by a bound containing one integer i and a comma +matches a sequence of i or more matches of the atom. An atom followed +by a bound containing two integers i and j matches a +sequence of i through j (inclusive) matches of the atom. +Both arguments must 0 >= value <= RE_DUP_MAX (default 255), +and if there are two of them, the second must be bigger or equal to the +first. +
+[a-dX]
+ +
+[^a-dX]
+ +
+Any character which is (not if ^ is used) either a, b, +c, d or X. To include ] it has to be +written first. To include - it has to be written first or last. +So [0-9] matches any decimal digit. All character that does not +have a defined mening inside a [] pair has no special meaning +and matches only itself.
+ +
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
+ +
+[[.characters.]]
+ +
+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 ch collating element, +then the RE [[.ch.]]*c matches the first five characters of chchcc.
+ +
+[=character-class=]
+ +
+An equivalence class, standing for the sequences of characters of all collating +elements equivalent to that one, including itself. For example, if o +and (+) are the members of an equivalence class, then [[=o=]], +[[=(+)=]], and [o(+)] are all synonymous. An equivalence +class may not be an endpoint of a range.
+ +
+[:character_class:]
+ +
+Within a bracket expression, the name of a character class enclosed in +[: and :] stands for the list of all characters belonging +to that class. Standard character class names are:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
alnum digit punct 
alpha graph space 
blank lower upper 
cntrl print xdigit 
+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. +
mysql> select "justalnums" regexp "[[:alnum:]]+";       -> 1
+mysql> select "!!" regexp "[[:alnum:]]+";               -> 0
+ +
  • +[[:<:]]
  • + +
  • +[[:>:]] 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.
  • + +
    mysql> select "a word a" regexp "[[:<:]]word[[:>:]]";      -> 1
    +mysql> select "a xword a" regexp "[[:<:]]word[[:>:]]";     -> 0
    +
    + +
    mysql> select "weeknights" regexp "^(wee|week)(knights|nights)$"; -> 1
    +  + + diff --git a/mozilla/webtools/bonsai/cvsview2.cgi b/mozilla/webtools/bonsai/cvsview2.cgi new file mode 100755 index 00000000000..ac903c7c2af --- /dev/null +++ b/mozilla/webtools/bonsai/cvsview2.cgi @@ -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 = ; + $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 = ; + } + + # 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.
    \n"; + print "\n"; + exit; + } +} +foreach $root (@SRCROOTS) { + $dir = "$root/$opt_subdir"; + if (-d $dir) { + $found = 1; + last; + } +} +if (!$found) { + print "Error: $opt_subdir not found in " + .join(',', @SRCROOTS), "\n"; + exit; +} + +# Create top-level frameset document. +sub do_diff_frameset { + chdir($dir); + + print "$opt_file: $opt_rev1 vs. $opt_rev2\n"; + print "\n"; + + print " \n"; + + print " \n"; + print "\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 "\n"; + print "\n"; + print ""; + print "\n"; + + print "$opt_file: $opt_rev1 vs. $opt_rev2\n"; + + print '
    '; + + 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 ""; + + print ""; + print ""; + + print "
    "; + print ""; + print ""; + print "\n"; + print ""; + print "\n"; + print ""; + print "\n"; + print "
    diff: Change diff parameters.
    blame:Annotate line authors.
    lxr: Browse source as hypertext.
    "; + print "
    "; + + print ""; + print "
    "; + print ""; + print "
    "; + + $anchor_num = 0; + while () { + # Get one command from the diff file + if (/^(c|a)(\d+)/) { + $line = $2; + while () { + last if /^\.$/; + } + } elsif (/^d(\d+)/) { + $line = $1; + } else { + print "Internal error:", + " unknown command $_", + " at $. in $opt_file $opt_rev1\n"; + } + + print ' ' x (4 - length($line)); + print "$line "; + $anchor_num++; + } + close(RCSDIFF); + + print '
    '; + print "
    \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 () { + 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 ""; + print "$opt_file: $opt_rev1 vs. $opt_rev2\n"; + print ""; + print ""; + + 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\n"; +} + + +# Show specified CVS log entry. +sub do_log { + + chdir($dir); + + print "$opt_file: $opt_rev CVS log entry\n"; + print '
    ';
    +    open(RCSLOG, "rlog -r$opt_rev $opt_file |");
    +
    +    while () {
    +        last if (/^revision $opt_rev$/);
    +    }
    +
    +    while () {
    +        last if (/^===============================================/);
    +        print "$_
    "; + } + close(RCSLOG); + + print '
    '; +} + + +# +# 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 = "
    "; + + foreach $path (split('/',$opt_subdir)) { + $link_path .= $path; + $output .= "$path/ "; + $link_path .= '/'; + } + chop ($output); + + if ($opt_branch) { + $output .= "
    Branch: $opt_branch"; + } + $output .= "
    "; + + EmitHtmlHeader("CVS Differences", $output); + + chdir($dir); + + print "\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 "\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 '\n"; + last; + } + + my $href_open = ""; + my $href_close = ""; + if ( $prev && $rev ) { + $href_open = "$href_open$rev$href_close
    "; + print "$revision_author{$rev}"; + } + + print "
    \n"; + + if (0) { + print "\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 "\n"; + } + print "\n";} + } + + print "
    "; + print "$file
    "; + print "Change Log\n"; + print "
    '; + print ''; + print "Prior revisions", "
    $revision_author{$rev}", + "
    \n"; + print '
    '; + print ''; + print ""; + print 'New Query:'; + print '
      '; + + + # 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
      \n", + 'Filename:', + '', + '', + "\n
      \n", + + 'Old version:', + '', + '', + "\n
      \n", + + 'New version:', + '', + '', + "\n
      \n"; + print '
      ', + '', + ' Show Whitespace', + '
      ', + ' Ignore Whitespace', + '
      ', + '', + ' Context Diffs', + '
      ', + ' Full Source Diffs'; + print '
      '; + print "\n"; + print '
    '; + print "
    \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 = "
    ";
    +    } else {
    +        # We don't want your stinking Windows font
    +        $font_tag = "
    ";
    +    }
    +    print "';
    +    print "";
    +    while () {
    +        $mark = 0;
    +        if (/^a(\d+)/) {
    +            $point = $1;
    +            &skip_to_line($point + 1, *OLDREV, *old_line_num);
    +            while () {
    +                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 () {
    +                last if (/^\.$/);
    +                if ($old_line_num <= $mark) {
    +                    $old_line = ;
    +                    $old_line_num++;
    +                } else {
    +                    $old_line = ''
    +                }
    +                &print_row($old_line, $change_bg_color, $_, $change_bg_color);
    +            }
    +            while ($old_line_num <= $mark) {
    +                $old_line = ;
    +                $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 = ) {
    +                $old_line_num++;
    +                &print_row($old_line, $deletion_bg_color, '', $stable_bg_color);
    +                last if ($. == $mark);
    +            }
    +        } else {
    +            print "
    Version $rev1Version $rev2
    Internal error:", + " 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 = ) { + $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 "
    \n"; + print "
    \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
    "; + $anchor_printed = 1; + } + + if ($opt_diff_mode eq 'context' && !$skip_line_printed && + $line_num - 5 <= $old_line_num) { + print "\n\n"; + print "'; + print ""; + &print_cell($line1, $color1); + &print_cell($line2, $color2); +} + +sub print_bottom { + print <<__BOTTOM__; +

    +

    ", + "Skipping to line $old_line_num: "; + $skip_line_printed = 1; + } + + $old_line = ; + $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 "" if (!$anchor_printed); + print ''; + $anchor_num++; +} + +sub print_cell { + local ($line, $color) = @_; + local ($i, $j, $k, $n); + local ($c, $newline); + + if ($color eq $stable_bg_color) { + print "$font_tag"; + } else { + print "$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; + 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
    +
    +
    + +  Mail feedback and feature requests to slamm.   +
    + + +__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; diff --git a/mozilla/webtools/bonsai/doadmin.cgi b/mozilla/webtools/bonsai/doadmin.cgi new file mode 100755 index 00000000000..cc1cf3d26a4 --- /dev/null +++ b/mozilla/webtools/bonsai/doadmin.cgi @@ -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 " +Clang! +

    The tree is now closed.

    +Mail has been sent notifying \"the hook\" and anyone subscribed to +bonsai-treeinterest. +

    +Click here +to send e-mail about it to clienteng. +" + + } + open { + AdminOpenTree [ParseTimeAndCheck [FormData lastgood]] \ + [info exists FORM(doclear)] + puts " +The floodgates are open. +

    The tree is now open.

    +Mail has been sent notifying \"the hook\" and anyone subscribed to +bonsai-treeinterest. +Click here +to send e-mail about it to clienteng. +" + } + tweaktimes { + set lastgoodtimestamp [ParseTimeAndCheck [FormData lastgood]] + set closetimestamp [ParseTimeAndCheck [FormData lastclose]] + puts " +Let's do the time warp again... +

    Times have been tweaked.

    +" + Log "Times tweaked: lastgood is [MyFmtClock $lastgoodtimestamp], closetime is [MyFmtClock $closetimestamp]" + } + editmotd { + LoadMOTD + if {![cequal [FormData origmotd] $motd]} { + puts " +Oops! +

    Someone else has been here!

    + +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 " +New MOTD +

    The message-of-the-day has been changed.

    +" + WriteMOTD + Log "New motd: $motd" + } + changepassword { + if {![cequal $FORM(newpassword) $FORM(newpassword2)]} { + puts " +Oops! +

    Mismatch!

    +The two passwords you typed didn't match. Click Back 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 " +Locksmithing complete. +

    Password changed.

    +The new password is now in effect." + PutsTrailer + exit + } +} + + +PutsTrailer + +WriteCheckins +Unlock + +exit diff --git a/mozilla/webtools/bonsai/doeditcheckin.cgi b/mozilla/webtools/bonsai/doeditcheckin.cgi new file mode 100755 index 00000000000..02e0cd9863f --- /dev/null +++ b/mozilla/webtools/bonsai/doeditcheckin.cgi @@ -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 + +" + +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 " +Oops! +

    Someone else has been here!

    + +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 " +Time trap +

    Can't grok the time

    +You entered a time of $timestr, and I can't understand it. Please +hit Back 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 diff --git a/mozilla/webtools/bonsai/doeditmessage.cgi b/mozilla/webtools/bonsai/doeditmessage.cgi new file mode 100755 index 00000000000..197f91e88a4 --- /dev/null +++ b/mozilla/webtools/bonsai/doeditmessage.cgi @@ -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 " +Oops! +

    Someone else has been here!

    + +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 " +New $filename +

    The file $filename has been changed.

    +" + +PutsTrailer + +exit diff --git a/mozilla/webtools/bonsai/doeditprofile.cgi b/mozilla/webtools/bonsai/doeditprofile.cgi new file mode 100755 index 00000000000..424504d1bf2 --- /dev/null +++ b/mozilla/webtools/bonsai/doeditprofile.cgi @@ -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 + +puts "Content-type: text/html + +" + +NOTDEF { + if {![cequal $FORM(password) $FORM(password2)]} { + puts { + Bzzzzt! +

    Passwords don't match.

    + The two password fields in the form don't contain the same thing. You must + type the same password in both places. +

    + Please click the Back button and try again. + } + exit + } +} + +Lock +LoadPerson $FORM(person) + +foreach i [array names person] { + if {[info exists FORM($i)]} { + set person($i) [FormData $i] + } +} + + + + +switch $FORM(contacttype) { + mailto { + set person(contact) [ConstructMailTo [FormData mailtoname] \ + [FormData mailtosubject]] + } + misc { + set person(contact) [FormData misccontact] + } +} + + + + +WritePerson $FORM(person) +Unlock + +puts " +Your profile has been updated.


    [GenerateProfileHTML]" + +PutsTrailer + +exit diff --git a/mozilla/webtools/bonsai/doeditwhiteboard.cgi b/mozilla/webtools/bonsai/doeditwhiteboard.cgi new file mode 100755 index 00000000000..abbe4b55e97 --- /dev/null +++ b/mozilla/webtools/bonsai/doeditwhiteboard.cgi @@ -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 + +Error -- pen stolen. +

    Someone else just changed the whiteboard.

    + +Somebody else has changed what's on the whiteboard. Your changes will +stomp over theirs. +

    +The whiteboard now reads: +


    +
    $whiteboard
    +
    +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. + +
    + + +Change the free-for-all whiteboard:
    +
    + +
    +" + PutsTrailer + exit +} + + +set newwhiteboard [string trimright [FormData whiteboard]] + +MailDiffs "whiteboard" $whiteboard $newwhiteboard + +set whiteboard $newwhiteboard +WriteWhiteboard + +Unlock + +puts " +Where's my blue marker? +

    The whiteboard has been changed.

    +The whiteboard now reads: +
    +
    $whiteboard
    +" + + + + +Log "Whiteboard changed to be: $whiteboard" + +PutsTrailer + +exit diff --git a/mozilla/webtools/bonsai/dolog.pl b/mozilla/webtools/bonsai/dolog.pl new file mode 100755 index 00000000000..84ca3e538fb --- /dev/null +++ b/mozilla/webtools/bonsai/dolog.pl @@ -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(, 0, -1); +$flag_debug = 0; +$flag_tagcmd = 0; +$repository = substr(, 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, "; + chop($repository); + close(REP); + } + $repository =~ s:^$cvsroot/::; + + if (!$flag_tagcmd) { + if( open( 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 () { + 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( ){ # 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(){ + 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; +} diff --git a/mozilla/webtools/bonsai/dotweak.cgi b/mozilla/webtools/bonsai/dotweak.cgi new file mode 100755 index 00000000000..15cec50bac9 --- /dev/null +++ b/mozilla/webtools/bonsai/dotweak.cgi @@ -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 + +" + +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 "

    Pick a different tree

    " + puts "You attempted to move checkins into the tree that they're" + puts "already in. Hit Back 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 "

    No command selected

    " + puts "You need to select one of the radio command buttons at the" + puts "bottom. Hit Back and try again." + PutsTrailer + exit + } +} + +WriteCheckins +Unlock + +puts " +

    OK, done.

    +The selected checkins have been $what" + +set treeid $origtree + +PutsTrailer +exit + diff --git a/mozilla/webtools/bonsai/editcheckin.cgi b/mozilla/webtools/bonsai/editcheckin.cgi new file mode 100755 index 00000000000..912f2c0cea5 --- /dev/null +++ b/mozilla/webtools/bonsai/editcheckin.cgi @@ -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 + + +Say the magic word. +

    Edit a checkin.

    + +Congratulations, you have found the hidden edit-a-checkin feature. Of course, +you need to know the magic word to do anything from here. + +

    + +

    + + + + + + + +" + +if {![info exists info(notes)]} { + set info(notes) "" +} + +foreach i {person dir files notes} { + puts "" + puts "" +} + +proc CheckString {value} { + if {$value} { + return "CHECKED" + } else { + return "" + } +} + +puts " + + + + + +
    Password:
    When: +
    $i:
    Tree state:Open +
    Closed +
    Log message:
    +Check this box to blow away this checkin entirely.
    + +" + +foreach i [lsort [array names info]] { + puts "" +} +puts "" + +puts "" + + + +puts "
    " + +PutsTrailer + +exit diff --git a/mozilla/webtools/bonsai/editmessage.cgi b/mozilla/webtools/bonsai/editmessage.cgi new file mode 100755 index 00000000000..7f91a7d1d5d --- /dev/null +++ b/mozilla/webtools/bonsai/editmessage.cgi @@ -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 + + + + +We don't need no stinkin' HTML compose window + + + +

    Message editor

    " + +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 $filename 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: + +" + +proc PutDoc {name desc} { + puts "" + puts "" + puts "" + puts "" +} + + +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 "
    %$name%Replaced by the $desc

    Uh, hey, this isn't a legal file for" + puts "you to be editing here!" + PutsTrailer + exit + } +} + +puts " + +

    + +Password:
    + + +
    + +
    + + " + + +PutsTrailer + +exit diff --git a/mozilla/webtools/bonsai/editprofile.cgi b/mozilla/webtools/bonsai/editprofile.cgi new file mode 100755 index 00000000000..7693a46b059 --- /dev/null +++ b/mozilla/webtools/bonsai/editprofile.cgi @@ -0,0 +1,109 @@ +#!/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 + +LoadPerson $FORM(person) + +puts "Content-type: text/html + +" + +NOTDEF { + if {![cequal $FORM(password) $person(password)]} { + puts "Bzzzzt!" + puts "

    Invalid password.

    " + puts "Please click the Back button and try again." + exit + } +} + + +puts " +Tell us about yourself... +

    Profile for $person(name)

    +
    + + + + + + + + + +" + +NOTDEF { + puts " + + + + + + +} + +puts " +
    Real name:
    Contact:" + + +set mailmatch 0 +if {[regexp -- {^Send mail to (.*)$} \ + $person(contact) foo name1 subject name2]} { + if {[cequal $name1 $name2]} { + set mailmatch 1 + } +} +if {$mailmatch} { + set checked "CHECKED" +} else { + set name1 $person(name) + set subject "Build busted" + set checked {} +} + + + +puts " + Send mail to + with subject +
    " + +if {$mailmatch} { + set checked {} + set value {} +} else { + set checked "CHECKED" + set value $person(contact) +} + +puts " + Other: +
    Password:
    Retype password:
    +Other info (office phone, home phone numbers, graffiti, whatever): +
    + +
    +
    +" + +PutsTrailer + +exit diff --git a/mozilla/webtools/bonsai/editwhiteboard.cgi b/mozilla/webtools/bonsai/editwhiteboard.cgi new file mode 100755 index 00000000000..6cc46702517 --- /dev/null +++ b/mozilla/webtools/bonsai/editwhiteboard.cgi @@ -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 + +Scritch, scritch. +
    + + + +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\".) + +

    + +Change the free-for-all whiteboard:
    +
    + +

    +" + +PutsTrailer + +exit diff --git a/mozilla/webtools/bonsai/globals.tcl b/mozilla/webtools/bonsai/globals.tcl new file mode 100755 index 00000000000..0a35ad9242f --- /dev/null +++ b/mozilla/webtools/bonsai/globals.tcl @@ -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 {&} +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 "

    Can't write checkins file; not viewing" + puts "current info." + 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 "Send mail to $name" +} + + + +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 "Error -- Couldn't contact the directory server.

    $errinfo
    " + } + + set result "" + + while {[gets $fid line] >= 0} { + if {[regexp -- {^([a-z]*): (.*)$} $line foo n v]} { + lappend value($n) $v + } + } + + if {[catch {close $fid} errinfo]} { + return "Error -- problem running ldapsearch.
    $errinfo
    " + } + + foreach i $namelist { + foreach v $value($i) { + append result "" + append result "" + } + } + append result "
    $title($i):$v
    " + + 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 "Bzzzzt!" + puts "

    Invalid password.

    " + puts "Please click the Back 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 " +Time trap +

    Can't grok the time

    +You entered a time of $timestr, and I can't understand it. Please +hit Back 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 +} diff --git a/mozilla/webtools/bonsai/handleAdminMail.tcl b/mozilla/webtools/bonsai/handleAdminMail.tcl new file mode 100755 index 00000000000..7658c2fa04f --- /dev/null +++ b/mozilla/webtools/bonsai/handleAdminMail.tcl @@ -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 diff --git a/mozilla/webtools/bonsai/handleCheckinMail.tcl b/mozilla/webtools/bonsai/handleCheckinMail.tcl new file mode 100755 index 00000000000..40593bb9670 --- /dev/null +++ b/mozilla/webtools/bonsai/handleCheckinMail.tcl @@ -0,0 +1,36 @@ +#!/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. + + + +if {[llength $argv] > 0} { + cd [lindex $argv 0] +} else { + cd [file dirname $argv0] +} + +set filename data/temp.[id process] + +catch {unlink $filename} +exec cat >> $filename +catch {chmod 0666 $filename} +exec ./addcheckin.tcl $filename +# unlink $filename + +exit diff --git a/mozilla/webtools/bonsai/header.pl b/mozilla/webtools/bonsai/header.pl new file mode 100644 index 00000000000..57246f247da --- /dev/null +++ b/mozilla/webtools/bonsai/header.pl @@ -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 "$doctitle"; + print ""; + + if (open(BANNER, ") { print; } + close BANNER; + } elsif (open(BANNER, "<../bonsai/data/banner.html")) { + while () { print; } + close BANNER; + } + + print ""; + print " \n"; + print " \n"; + print "
    \n"; + print " \n"; + print " \n"; + print "
    \n"; + print " $heading\n"; + print "
    \n"; + print " $subheading\n"; + print "
    \n"; + print "
    \n"; + + if (open(BLURB, ") { print; } + close BLURB; + } + + print "
    \n"; +} + +sub EmitHtmlHeader { + my($heading,$subheading) = @_; + EmitHtmlTitleAndHeader($heading,$heading,$subheading); +} + +1; diff --git a/mozilla/webtools/bonsai/index.html b/mozilla/webtools/bonsai/index.html new file mode 100644 index 00000000000..2a5b49d22d6 --- /dev/null +++ b/mozilla/webtools/bonsai/index.html @@ -0,0 +1,12 @@ + + + + + +Going to
    +
    + toplevel.cgi +
    + + diff --git a/mozilla/webtools/bonsai/indextest.pl b/mozilla/webtools/bonsai/indextest.pl new file mode 100755 index 00000000000..a667fc8217e --- /dev/null +++ b/mozilla/webtools/bonsai/indextest.pl @@ -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( ){ + chop; + ($o,$d) = split(/\|/); + seek(CI, $o, 0); + $line = ; + ($j,$d1) = split(/\|/); + print "$d|$d1\n"; + } + diff --git a/mozilla/webtools/bonsai/lloydcgi.pl b/mozilla/webtools/bonsai/lloydcgi.pl new file mode 100755 index 00000000000..c4af11209e8 --- /dev/null +++ b/mozilla/webtools/bonsai/lloydcgi.pl @@ -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); +} diff --git a/mozilla/webtools/bonsai/localprofile.cgi b/mozilla/webtools/bonsai/localprofile.cgi new file mode 100755 index 00000000000..672e47a6e07 --- /dev/null +++ b/mozilla/webtools/bonsai/localprofile.cgi @@ -0,0 +1,79 @@ +#!/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 + +proc PutsLDAPDisclaimer {} { + puts " +
    + Yes, yes, we will punt all this stuff and use the Directory Server, +but we have some exploring and hacking to do first. Meanwhile, we at +least try to display the phonebook record below. + +" +} + + + +puts "Content-type: text/html + +" + + +puts [GenerateProfileHTML $FORM(person)] + +puts " +
    + + +To change this profile, " + +NOTDEF { + puts " type in the associated password (if any) and " +} + +puts " +click on Edit. + +
    + +" + +NOTDEF { + puts " +Password: +" +} + +puts " +
    + + +
    + +See someone else's profile. + +" + +PutsLDAPDisclaimer + + +PutsTrailer + +exit diff --git a/mozilla/webtools/bonsai/maketables.sh b/mozilla/webtools/bonsai/maketables.sh new file mode 100755 index 00000000000..ecc4d7f3c3c --- /dev/null +++ b/mozilla/webtools/bonsai/maketables.sh @@ -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 diff --git a/mozilla/webtools/bonsai/moduleanalyse.cgi b/mozilla/webtools/bonsai/moduleanalyse.cgi new file mode 100755 index 00000000000..4eb973f8024 --- /dev/null +++ b/mozilla/webtools/bonsai/moduleanalyse.cgi @@ -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 + +"; + +require 'modules.pl'; + +print " + +CVS Module Analyzer +"; + +cvsmenu("align=right width=20%"); + +print " +

    CVS Module Analyzer

    +

    This tool will show you the directories and files that make up a given +cvs module. +"; + + +print " +

    +

    +"; + + +# +# module selector +# +print " + +Module: +\n"; + + +print " +
    +
    + + +
    "; + + +if( $form{module} ne '' ){ + $mod = $form{module}; + print "

    Examining Module '$mod'

    \n\n"; + $mod_map = &get_module_map( $mod ); + for $i (sort keys %$mod_map) { + if( -d "$CVS_ROOT/$i"){ + print "
    Dir:   "; + print "$i"; + } + elsif ( -r "$CVS_ROOT/$i,v" ){ + print "
    File:  "; + print "$i"; + } + else { + print "
    Error: "; + print "$i : Not a file or a directory."; + } + + if( $mod_map->{$i} == $IS_LOCAL ){ + print " LOCAL"; + } + 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]"; + } +} diff --git a/mozilla/webtools/bonsai/modules.pl b/mozilla/webtools/bonsai/modules.pl new file mode 100755 index 00000000000..0c77d6d9f6b --- /dev/null +++ b/mozilla/webtools/bonsai/modules.pl @@ -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 = ) ){ + 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; +} diff --git a/mozilla/webtools/bonsai/multidiff.cgi b/mozilla/webtools/bonsai/multidiff.cgi new file mode 100755 index 00000000000..f9325680d95 --- /dev/null +++ b/mozilla/webtools/bonsai/multidiff.cgi @@ -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 + +
    
    +";
    +
    +@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/){
    +        print "$who:  $_";
    +    }
    +    $didone = 1;
    +}
    +
    +if ($didone == 0) {
    +    print "No changes were selected.  Please press Back 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];
    +}
    diff --git a/mozilla/webtools/bonsai/myglobrecur.tcl b/mozilla/webtools/bonsai/myglobrecur.tcl
    new file mode 100644
    index 00000000000..c2b41f3a663
    --- /dev/null
    +++ b/mozilla/webtools/bonsai/myglobrecur.tcl
    @@ -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 {}
    +}
    diff --git a/mozilla/webtools/bonsai/openmessage b/mozilla/webtools/bonsai/openmessage
    new file mode 100644
    index 00000000000..2095bbdf58f
    --- /dev/null
    +++ b/mozilla/webtools/bonsai/openmessage
    @@ -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
    +
    +
    +
    +

    You are responsible to make sure the build works.

    + +You just checked into %dir% the files %files%. At +about %nextclose%, 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. + +

    + +Any further checkins you make before the tree closes will not +cause you to receive more copies of this mail, but you'll be held +responsible for them too. + +

    + +For more info on the current state of the tree, see the +Bonsai main page. + +

    + +Your contact info and other vital data is listed below. Please +update +this info immediately if it is at all inaccurate or incorrect. + +


    + +%profile% diff --git a/mozilla/webtools/bonsai/perlifyconfig.tcl b/mozilla/webtools/bonsai/perlifyconfig.tcl new file mode 100755 index 00000000000..94d5ff259d7 --- /dev/null +++ b/mozilla/webtools/bonsai/perlifyconfig.tcl @@ -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 diff --git a/mozilla/webtools/bonsai/processqueue.pl b/mozilla/webtools/bonsai/processqueue.pl new file mode 100755 index 00000000000..a17438e6a39 --- /dev/null +++ b/mozilla/webtools/bonsai/processqueue.pl @@ -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"; +} diff --git a/mozilla/webtools/bonsai/profile.cgi b/mozilla/webtools/bonsai/profile.cgi new file mode 100755 index 00000000000..76972069fb7 --- /dev/null +++ b/mozilla/webtools/bonsai/profile.cgi @@ -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 { +Uh, who? +

    Who would you like to know more about?

    +Please enter the username of the person whose Bonsai profile +you'd like to see. +

    +

    +User: +
    + } + 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 { +Uh, who? +

    Who would you like to know more about?

    +There doesn't seem to be anybody with e-mail address +$FORM(person). + +

    + +Please enter the username of the person whose Bonsai profile +you'd like to see. +

    +

    +User: +
    + } + 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"] + + +What a hack. +One moment while we whisk you away to the appropriate phonebook page..." + + + +exit diff --git a/mozilla/webtools/bonsai/rebuildcvshistory.cgi b/mozilla/webtools/bonsai/rebuildcvshistory.cgi new file mode 100755 index 00000000000..8e67ccd3a60 --- /dev/null +++ b/mozilla/webtools/bonsai/rebuildcvshistory.cgi @@ -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 + +" + + 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 "
    Putting entries ($count unique descriptions) into database...

    " +# 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.
    " +# 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 "


    " +# 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
    " +# 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 "

    Done. $numfiles files checked; $numtags tags created.

    " + diff --git a/mozilla/webtools/bonsai/rebuilddatabase.tcl b/mozilla/webtools/bonsai/rebuilddatabase.tcl new file mode 100755 index 00000000000..a6c57e853e7 --- /dev/null +++ b/mozilla/webtools/bonsai/rebuilddatabase.tcl @@ -0,0 +1,196 @@ +#!/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 + +ConnectToDatabase + +set repository [lindex $argv 0] +set startdate [lindex $argv 1] + +if {![cequal $startdate ""]} { + set startdate [convertclock $startdate] +} + + +regsub -all -- / $repository _ mungedname + +set infid [open data/checkinlog$mungedname "r"] + +# SendSQL "select descid from checkins where repository='[SqlQuote $repository]'" +# +# set ids(zz) 1 +# unset ids(zz) +# while {[MoreSQLData]} { +# set ids([lindex [FetchSQLData] 0]) 1 +# } +# +# set list [array names ids] +# +# +# set num [llength $list] +# +# set d 0 +# foreach i $list { +# SendSQL "delete from descs where id=$i" +# incr d +# if {$d % 100 == 0} { +# puts "Deleted $d of $num old descriptions
    " +# } +# } +# +# +# SendSQL "delete from checkins where repository = '[SqlQuote $repository]'" + + +set buffer {} +set desc {} +set indesc 0 + +if {![cequal $startdate ""]} { + puts "Searching for first entry after [fmtclock $startdate] ...
    " + flush stdout + + if {![catch {set index [open data/index$mungedname r]}]} { + while {[gets $index line] >= 0} { + lassign [split $line "|"] offset date + if {$date <= $startdate} { + seek $infid $offset + puts "Seeked to position $offset.
    " + flush stdout + break + } + } + close $index + } + + set count 0 + set foundfirst 0 + while {!$foundfirst && [gets $infid line] >= 0} { + if {$indesc} { + if {[cequal $line ":ENDLOGCOMMENT"]} { + set indesc 0 + } + } else { + if {[cequal $line "LOGCOMMENT"]} { + set indesc 1 + } else { + lassign [split $line "|"] chtype date + set problem [catch { + if {$date >= $startdate} { + if {$date - $startdate < 10 * 24 * 60 * 60} { + set foundfirst 1 + } + } + incr count + if {$count % 100 == 0} { + puts "[fmtclock $date]
    " + flush stdout + } + } errorinfo] + if {$problem} { + puts "Date parsing problem? $date $errorinfo" + flush stdout + } + } + } + } + + set buffer "$line\n" + puts "OK, found first line:\n$buffer
    " + flush stdout +} + +set done 0 +while {[gets $infid line] >= 0} { + if {$indesc} { + if {[cequal $line ":ENDLOGCOMMENT"]} { + if {$done % 100 == 0} { + lassign [split $buffer "|"] chtype date + if {[catch {set prettydate [fmtclock $date]}]} { + puts "Couldn't format date; buffer is $buffer " + } else { + puts "$done done. ([fmtclock $date])
    " + flush stdout + } + } + AddToDatabase $buffer $desc + set buffer {} + set desc {} + set indesc 0 + incr done + } else { + append desc $line + append desc "\n" + } + } else { + if {[cequal $line "LOGCOMMENT"]} { + set indesc 1 + } else { + append buffer $line + append buffer "\n" } + } +} +close $infid + +# Now get rid of any dangling descriptions. Sigh; there ought to be a better +# way. + +puts "Gathering unique ids from descs ...
    " +flush stdout +SendSQL "lock tables descs read,checkins read" +SendSQL "select id from descs" +set ids(zz) 1 +unset ids(zz) +while {[MoreSQLData]} { + set ids([lindex [FetchSQLData] 0]) 1 +} +puts "... [array size ids] found.
    " +puts "Gathering unique ids from checkins ...
    " +flush stdout +set cids(zz) 1 +unset cids(zz) +SendSQL "select distinct descid from checkins" +while {[MoreSQLData]} { + set cids([lindex [FetchSQLData] 0]) 1 +} +puts "... [array size cids] found.
    " +flush stdout + +set n 0 +set remove {} +foreach i [array names ids] { + if {![info exists cids($i)]} { + lappend remove $i + incr n + } +} + +puts "Removing $n unused descs:
    " +SendSQL "unlock tables" + +set n 0 +foreach i $remove { + SendSQL "delete from descs where id = $i" + incr n + if {$n % 100 == 0} { + puts "Deleted $n.
    " + flush stdout + } +} diff --git a/mozilla/webtools/bonsai/rebuildtaginfo.cgi b/mozilla/webtools/bonsai/rebuildtaginfo.cgi new file mode 100755 index 00000000000..a895d2afb6d --- /dev/null +++ b/mozilla/webtools/bonsai/rebuildtaginfo.cgi @@ -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 + +" + +CheckPassword $FORM(password) + +Lock +LoadTreeConfig +Unlock + +set repository $treeinfo($treeid,repository) +regsub -all -- / $repository _ mungedname + +puts "

    Searching for tags in all files in $repository ...

    " +flush stdout + +set numfiles 0 +set numtags 0 + +my_for_recursive_glob filename $repository "*,v" { + puts "$filename
    " + 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 "
    " +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
    " + 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 "

    Done. $numfiles files checked; $numtags tags created.

    " + +PutsTrailer diff --git a/mozilla/webtools/bonsai/repophook.cgi b/mozilla/webtools/bonsai/repophook.cgi new file mode 100755 index 00000000000..c1067e21acf --- /dev/null +++ b/mozilla/webtools/bonsai/repophook.cgi @@ -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 + +" + +CheckPassword $FORM(password) + +set startfrom [ParseTimeAndCheck [FormData startfrom]] + +Lock +LoadTreeConfig +LoadCheckins +set checkinlist {} +WriteCheckins +Unlock + + +puts " Rebooting, please wait... + +

    Recreating the hook

    + +

    $treeinfo($treeid,description)

    + +

    +Searching for first checkin after [MyFmtClock $startfrom]...

    " + +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...
    " + 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!
    " + puts "

    [value_quote $line]

    " + } + set $lastdate $date + if {$foundfirst} { + append buffer "$line\n" + } else { + if {$date >= $startfrom} { + if {$date >= $now} { + puts "Found a future date! (ignoring):
    " + puts "

    [value_quote $line]

    " + flush stdout + } else { + set foundfirst 1 + puts "Found first line:

    [value_quote $line]

    " + puts "OK, now processing checkins...

    " + flush stdout + set buffer "$line\n" + set count 0 + } + } else { + incr count + if {$count % 2000 == 0} { + puts "Skipped $count lines...

    " + 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 diff --git a/mozilla/webtools/bonsai/reposfiles.pl b/mozilla/webtools/bonsai/reposfiles.pl new file mode 100755 index 00000000000..cdc47ca5fd2 --- /dev/null +++ b/mozilla/webtools/bonsai/reposfiles.pl @@ -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"); + } +} diff --git a/mozilla/webtools/bonsai/rview.cgi b/mozilla/webtools/bonsai/rview.cgi new file mode 100755 index 00000000000..a88aab804a4 --- /dev/null +++ b/mozilla/webtools/bonsai/rview.cgi @@ -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 + +"; + + +&setup_script; +print $script_str; + + +if( $CVS_ROOT eq "" ){ + $CVS_ROOT = pickDefaultRepository(); +} + +validateRepository($CVS_ROOT); + +if( $rev ne "" ){ + $s = "for branch $rev"; +} + +print " +Repository Directory $CVS_ROOT/$dir $s"; + +$output = "

    "; + +($dir_head, $dir_tail) = $dir =~ m@(.*/)?(.+)@; +foreach $path (split('/',$dir_head)) { + $link_path .= $path; + $output .= " +
    +Goto Directory: + + + + +
    +
    +Branch: + + + + + + + +"; + +@dirs = (); + +while( <*> ){ + if( -d $_ ){ + push @dirs, $_; + } +} + +if( @dirs != 0 ){ + $j = 1; + $split = int(@dirs/4)+1; + print "

    Directories:
    "; + + + for $i (@dirs){ + $form{"dir"} = ($dir ne "" ? "$dir/$i" : $i); + $anchor = &make_cgi_args; + print "
    $i\n"; + if( $j % $split == 0 ){ + print "\n
    \n"; + } + $j++; + } + $form{"dir"} = $dir; + print "\n
    \n"; +} + + +print "

    Files:"; +print "
    "; +@files = <*,v>; +$j = 1; +$split = int(@files/4)+1; + +for $_ (@files){ + $_ =~ s/\,v//; + print "\n"; + print "
    $_\n"; + if( $j % $split == 0 ){ + print "\n
    \n"; + } + $j++; +} +print "\n
    \n"; + + +sub setup_script { + +$script_str =<<'ENDJS'; + + + + + +ENDJS + +} + diff --git a/mozilla/webtools/bonsai/show2.cgi b/mozilla/webtools/bonsai/show2.cgi new file mode 100755 index 00000000000..c9538f5508f --- /dev/null +++ b/mozilla/webtools/bonsai/show2.cgi @@ -0,0 +1,348 @@ +#!/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]
    " + 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 " +" + +if {[info exists FORM(person)]} { + puts "Checkins for $FORM(person)" + puts "

    Checkins for $FORM(person)

    " + 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 "$str" + puts "

    $str

    " + set list {} + foreach i $checkinlist { + upvar #0 $i info + if {$info(date) >= $min && $info(date) <= $max} { + lappend list $i + } + } +} else { + puts "All checkins" + puts "

    All Checkins

    " + set list $checkinlist +} + +if {$readonly} { + puts "

    Be aware that you are looking at an old hook!

    " +} + + +puts "(Current sort is by $FORM(sort); 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 "" +} + + +puts " + + +" + +if {$tweak} { + puts "" +} + +puts " +" + +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 "
    When +Tree state +Who +Directory +Files" + +if {$delta_size} { + puts "+/-" +} + +puts " +Description +
    " + } + puts "" + if {$tweak} { + puts "" + } + puts "" + puts "" + set peoplearray($info(person)) 1 + puts "" + puts "" + puts "" + if {$delta_size} { + puts "" + } + if {[info exists info(fullinfo)]} { + foreach f $info(fullinfo) { + lassign $f file version + append versioninfo "$info(person)|$info(dir)|$file|$version," + } + } + puts "" + puts "" +} +puts "
    " + puts "[fmtclock $info(date) "%m/%d %H:%M"]" + if {$info(treeopen)} { + puts "open" + } else { + puts "CLOSED" + } + if {[info exists info(notes)]} { + if {![cequal $info(notes) ""]} { + puts "
    $info(notes)" + } + } + puts "
    $info(person)[BreakBig $info(dir)]" + foreach f $info(files) { + puts "$f" + } + + puts "" + if {$info(removed) < 0} { + set str_removed $info(removed) + } else { + set str_removed "-0" + } + puts "+$info(added)
    $str_removed" + puts "
    $info(log)
    " + + +if {$delta_size} { + set deltastr "     Lines changed ($total_added/$total_removed)." +} else { + set deltastr "" +} + + +puts "[llength $list] checkins listed. $deltastr" + + +if {$tweak} { + puts " +
    +Check the checkins you wish to affect. Then select one of the below options. +And type the magic word. Then click on submit. +

    + +Delete these checkins.
    +Set the tree state on these checkins to be Open.
    +Set the tree state on these checkins to be Closed.
    +Move these checkins over to this tree: +

    +Password: +
    + +

    " +} else { + puts "          " + puts "
    Tweak some of these checkins." + puts "

    " + puts "
    " + puts "" + puts "" + puts "
    " +} + +if {[info exists FORM(ltabbhack)]} { + puts "" + puts "" +} + + +PutsTrailer diff --git a/mozilla/webtools/bonsai/showcheckins.cgi b/mozilla/webtools/bonsai/showcheckins.cgi new file mode 100755 index 00000000000..1bd069e057b --- /dev/null +++ b/mozilla/webtools/bonsai/showcheckins.cgi @@ -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]
    " + 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 " +" + +if {[info exists FORM(person)]} { + puts "Checkins for $FORM(person)" + puts "

    Checkins for $FORM(person)

    " + 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 "$str" + puts "

    $str

    " + set list {} + foreach i $checkinlist { + upvar #0 $i info + if {$info(date) >= $min && $info(date) <= $max} { + lappend list $i + } + } +} else { + puts "All checkins" + puts "

    All Checkins

    " + set list $checkinlist +} + +if {$readonly} { + puts "

    Be aware that you are looking at an old hook!

    " +} + + +puts "(Current sort is by $FORM(sort); 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 "
    " +} + + +puts " + + +" + +if {$tweak} { + puts "" +} + +puts " +" + +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 "
    When +Tree state +Who +Directory +Files" + +if {$delta_size} { + puts "+/-" +} + +puts " +Description +
    " + } + puts "" + if {$tweak} { + puts "" + } + puts "" + puts "" + set peoplearray($info(person)) 1 + puts "" + puts "" + puts "" + if {$delta_size} { + puts "" + } + if {[info exists info(fullinfo)]} { + foreach f $info(fullinfo) { + lassign $f file version + append versioninfo "$info(person)|$info(dir)|$file|$version," + } + } + puts "" + puts "" +} +puts "
    " + puts "[fmtclock $info(date) "%m/%d %H:%M"]" + if {$info(treeopen)} { + puts "open" + } else { + puts "CLOSED" + } + if {[info exists info(notes)]} { + if {![cequal $info(notes) ""]} { + puts "
    $info(notes)" + } + } + puts "
    $info(person)[BreakBig $info(dir)]" + foreach f $info(files) { + puts "$f" + } + + puts "" + if {$info(removed) < 0} { + set str_removed $info(removed) + } else { + set str_removed "-0" + } + puts "+$info(added)
    $str_removed" + puts "
    $info(log)
    " + + +if {$delta_size} { + set deltastr "     Lines changed ($total_added/$total_removed)." +} else { + set deltastr "" +} + + +puts "[llength $list] checkins listed. $deltastr" + + +if {$tweak} { + puts " +
    +Check the checkins you wish to affect. Then select one of the below options. +And type the magic word. Then click on submit. +

    + +Delete these checkins.
    +Set the tree state on these checkins to be Open.
    +Set the tree state on these checkins to be Closed.
    +Move these checkins over to this tree: +

    +Password: +
    + +

    " +} else { + puts "          " + puts "Tweak some of these checkins." + puts "

    " + puts "
    " + puts "" + puts "" + puts "
    " +} + +if {[info exists FORM(ltabbhack)]} { + puts "" + puts "" +} + + +PutsTrailer diff --git a/mozilla/webtools/bonsai/switchtree.cgi b/mozilla/webtools/bonsai/switchtree.cgi new file mode 100755 index 00000000000..d9249d6a926 --- /dev/null +++ b/mozilla/webtools/bonsai/switchtree.cgi @@ -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 + + +George, George, George of the jungle... + +Which tree would you like to see? +" + +puts "
    " + +foreach i $treelist { + if {![info exists treeinfo($i,nobonsai)]} { + puts "" + puts "$treeinfo($i,description)
    " + } +} + +puts "
    " + +PutsTrailer + +exit diff --git a/mozilla/webtools/bonsai/testlock.pl b/mozilla/webtools/bonsai/testlock.pl new file mode 100755 index 00000000000..2ebf0b05fa1 --- /dev/null +++ b/mozilla/webtools/bonsai/testlock.pl @@ -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(); diff --git a/mozilla/webtools/bonsai/toplevel.cgi b/mozilla/webtools/bonsai/toplevel.cgi new file mode 100755 index 00000000000..2dcb7ed667e --- /dev/null +++ b/mozilla/webtools/bonsai/toplevel.cgi @@ -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 + + +($openword) Bonsai -- the art of effectively controlling trees + + +

    Bonsai -- Tree Control

    + +
    +

    + + +foreach t $treelist { + if {![info exists treeinfo($t,nobonsai)]} { + if {[cequal $t $treeid]} { + set c "SELECTED" + } else { + set c "" + } + puts "

    " + + + +if {$readonly} { + puts "

    Be aware that you are looking at an old hook!

    " +} + +puts "[fmtclock [getclock] "%R"]: The tree is currently " + +if {$treeopen} { + puts "OPEN
    " +} else { + puts "CLOSED
    " +} + +if {!$treeopen} { + puts "The tree has been closed since [MyFmtClock $closetimestamp]." +} +puts "
    " +puts "The last known good tree had a timestamp " +puts "of [fmtclock $lastgoodtimestamp "%D %T %Z"].
    " + +puts "
    $motd

    " + + +puts "
    " + +# 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 "Free-for-all whiteboard: (Changebars indicate changes within last [PrettyDelta $delta])
    [html_quote [read_file $filename]]

    " + +puts "Free-for-all whiteboard:
    [html_quote $whiteboard]

    " + + +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 "

    " + + 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 "Can't contact the directory server at $ldapserver:$ldapport -- $errvar" + } + + puts "" + puts "" + + foreach p $peoplelist { + if {[info exists closedcheckin($p)]} { + set extra " ([llength $closedcheckin($p)] while tree closed!)" + } else { + set extra "" + } + + puts " + + + +" + puts " +" + } + + puts "
    WhoWhatHow to contact
    $fullname($p) +$p[llength $people($p)] +[Pluralize change [llength $people($p)]]$extra$curcontact($p) +
    " + 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 "

    " + puts "Show all checkins.
    " + if {[cequal $treeid default]} { + puts "" + } else { + puts "" + } + puts "Send mail to \"the hook\".
    " +} 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 " +


    + + + + + + +
    Useful links Help corner
    +CVS Query Tool
    +Tinderbox continuous builds
    +Switch to look at a different tree or branch
    +Look at the Busted Tree Newsgroup
    +Look up someone in the phonebook.
    +Time warp -- view a different day's hook.
    +See some stupid statistics about recent checkins.
    +Administration menu.
    +
    + +Introduction to Bonsai.
    +Overview of our source tree strategy.
    +Changing someone else's contact info (yes you can!)
    +Dogbert build lore +
    +" + + +exit diff --git a/mozilla/webtools/bonsai/trapdoor.c b/mozilla/webtools/bonsai/trapdoor.c new file mode 100644 index 00000000000..c3f70ad8da9 --- /dev/null +++ b/mozilla/webtools/bonsai/trapdoor.c @@ -0,0 +1,7 @@ +#include +#include + +main(int argc, char** argv) { + printf("%s\n", crypt(argv[1], "aa")); + return 0; +} diff --git a/mozilla/webtools/bonsai/utils.pl b/mozilla/webtools/bonsai/utils.pl new file mode 100644 index 00000000000..141eef9e991 --- /dev/null +++ b/mozilla/webtools/bonsai/utils.pl @@ -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, ") { + 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 $_; +} diff --git a/mozilla/webtools/bonsai/viewold.cgi b/mozilla/webtools/bonsai/viewold.cgi new file mode 100755 index 00000000000..f45680ccda0 --- /dev/null +++ b/mozilla/webtools/bonsai/viewold.cgi @@ -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 + + +Let's do the time warp again... + +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 "
    " +puts "" +puts "
    " + +set value [lvarpop list] + +puts "" +puts "The current hook.
    " + +set count 1 +foreach i $list { + set value [lvarpop list] + puts "" + source [DataDir]/batch-$i + puts "Hook for tree that closed on [MyFmtClock $closetimestamp]
    " +} + +puts "" +puts "
    " + +PutsTrailer + +exit diff --git a/mozilla/webtools/registry/file.cgi b/mozilla/webtools/registry/file.cgi new file mode 100755 index 00000000000..14e467dec5e --- /dev/null +++ b/mozilla/webtools/registry/file.cgi @@ -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\n"; + +print "
    \n"; + +&load_extra_data; + + +$i = 0; +while( $i < @extra_text ){ + $t = $extra_text[$i]; + if( $u = $extra_url[$i] ){ + + print("
    $t\n"); + } + else { + print("
    $t\n"); + } + $i++; +} + +if( @extra_text ){ + print("
    \n"); +} + + +$dirname2 = $dirname; + +$dirname2 =~ s/^ns\///; + +print " +$linked_text + +
    + View Blame-Annotated Source +"; +if ($prev_rev ne '') { + print "
    View Diff $prev_rev vs. $rev"; +} else { + + print "
    " + ."View Diff's"; +} + +print "
    + View Logs +"; + +print " +
    "; + +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++; + } +} diff --git a/mozilla/webtools/registry/lloydcgi.pl b/mozilla/webtools/registry/lloydcgi.pl new file mode 100755 index 00000000000..0f89cb46fa0 --- /dev/null +++ b/mozilla/webtools/registry/lloydcgi.pl @@ -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; + } +} + diff --git a/mozilla/webtools/registry/who.cgi b/mozilla/webtools/registry/who.cgi new file mode 100755 index 00000000000..82fac4d2b4e --- /dev/null +++ b/mozilla/webtools/registry/who.cgi @@ -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\n"; + +print "
    \n"; +print "$email\n"; +print "\n"; + +&load_extra_data; + + +$i = 0; +while( $i < @extra_text ){ + $t = $extra_text[$i]; + if( $u = $extra_url[$i] ){ + + print("
    $t\n"); + } + else { + print("
    $t\n"); + } + $i++; +} + +if( @extra_text ){ + print("
    \n"); +} + +print " +
    + Send Mail + + + +
    + Check-ins within 7 days + +
    + +
    +
    +"; + +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++; + } +} diff --git a/mozilla/webtools/tinderbox/1afi003r.gif b/mozilla/webtools/tinderbox/1afi003r.gif new file mode 100644 index 0000000000000000000000000000000000000000..0b6bb07a36f7dcee1851c39115af49b22cfaccab GIT binary patch literal 12967 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 literal 0 HcmV?d00001 diff --git a/mozilla/webtools/tinderbox/Empty.html b/mozilla/webtools/tinderbox/Empty.html new file mode 100644 index 00000000000..388168653a4 --- /dev/null +++ b/mozilla/webtools/tinderbox/Empty.html @@ -0,0 +1 @@ +Click on the filename and line number in the log and the source will appear in this window. diff --git a/mozilla/webtools/tinderbox/README b/mozilla/webtools/tinderbox/README new file mode 100644 index 00000000000..7b7e5dd25ec --- /dev/null +++ b/mozilla/webtools/tinderbox/README @@ -0,0 +1,73 @@ +This is Tinderbox. See . + + + ========== + 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 . + +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 ??? diff --git a/mozilla/webtools/tinderbox/addimage.cgi b/mozilla/webtools/tinderbox/addimage.cgi new file mode 100755 index 00000000000..8636fb51984 --- /dev/null +++ b/mozilla/webtools/tinderbox/addimage.cgi @@ -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 "


    "; + print "
      Something went wrong:

      "; + print "

        "; + print $msg; + print "
      "; + print "

      "; + print "Hit \`Back' and try again."; + print "

    "; + 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 " + +


    +$quote

    +"; + + 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 " +
    + + +
    + + + + + + + + + + + +
    Image URL:$u2
    Caption:$q2
    + + Does that look right? + + +
    (If not, hit \`Back' and fix it.) +
    +
    +
    +"; + } + else { + &add_imagelog( $url, $quote, $width, $height ); + print "

    + Has been added

    + Return to Log"; + } + +} +else { + print " +

    Add an image and a funny caption.

    + +
      +

      This is about fun, and making your daily excursion to +Tinderbox a +novel experience. Engineers spend a lot of time here; it might as well +have some entertainment value. + +

      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. + +

        Thank you for playing nice.
      + +

      If you really find an image offensive, please +tell us +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. +

    + +

    + + + + + + + + + + + +
    Image URL:
    Caption:
    + + + +
    + +
    +

    +"; +} + +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"; + + $_ = ; + if (! m@^HTTP/[0-9.]+ 200@ ) { + Error "$them responded:
    $_"; + } + + my $ctype = ""; + while () { + # print "read: $_
    \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; +} diff --git a/mozilla/webtools/tinderbox/addnote.cgi b/mozilla/webtools/tinderbox/addnote.cgi new file mode 100755 index 00000000000..c2f654ceac4 --- /dev/null +++ b/mozilla/webtools/tinderbox/addnote.cgi @@ -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\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 "

    The following comment has been added to the log

    \n"; + + #print "$buildname \n $buildtime \n $errorparser \n $logfile \n $tree \n $enc_buildname \n"; + print "
    \n[$who - $now_str]\n$note\n
    "; + + print" +

    +Go back to the Error Log + +
    Go back to the build Page
    +"; + +} +else { + if( $buildname eq '' || $buildtime == 0 ){ + print "

    Invalid parameters

    \n"; + die "\n"; + } + +#print "$buildname \n $buildtime \n $errorparser \n $logfile \n $tree \n $enc_buildname \n"; + + print " +Add a Comment to the log +

    Add a Comment to the log

    + +
    + +
    Your email address: + + + + + + + +
    +"; +} diff --git a/mozilla/webtools/tinderbox/admintree.cgi b/mozilla/webtools/tinderbox/admintree.cgi new file mode 100755 index 00000000000..cccaa8120e9 --- /dev/null +++ b/mozilla/webtools/tinderbox/admintree.cgi @@ -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\n"; + +EmitHtmlHeader("administer tinderbox", "tree: $tree"); + +&load_data; + + +if( -r "$tree/mod.pl" ){ + require "$tree/mod.pl"; +} +else { + $message_of_day = ""; +} + +print " +
    +Password: + + +
    Message of the Day +
    +
    + +
    +"; + + +print " +
    +Password: + + +
    Trim Logs to days. (Tinderbox +shows 2 days history by default. You can see more by clicking show all). +
    +
    +
    +
    +" ; + + +print " + +Password:
    + + + + + + + + + + + + + +
    tinderbox tree name:
    cvs module name:
    cvs branch:
    + +
    +
    +
    + +Password:
    + + +"; + +$i = 1; +while( $i <= $name_count ){ + $n = $build_name_names->[$i]; + print ""; + print "$n
    \n"; + $i++; +} + +print " + +
    +
    +"; + + + + + diff --git a/mozilla/webtools/tinderbox/buildwho.pl b/mozilla/webtools/tinderbox/buildwho.pl new file mode 100755 index 00000000000..78a1856d748 --- /dev/null +++ b/mozilla/webtools/tinderbox/buildwho.pl @@ -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 = ; + 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 ); +} diff --git a/mozilla/webtools/tinderbox/clean.pl b/mozilla/webtools/tinderbox/clean.pl new file mode 100755 index 00000000000..1f0bec1d3e4 --- /dev/null +++ b/mozilla/webtools/tinderbox/clean.pl @@ -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( ){ + chop(); + #print "unlink $_\n"; + unlink $_; +} diff --git a/mozilla/webtools/tinderbox/copydata.pl b/mozilla/webtools/tinderbox/copydata.pl new file mode 100755 index 00000000000..d732419720b --- /dev/null +++ b/mozilla/webtools/tinderbox/copydata.pl @@ -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(){ + 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"; +} diff --git a/mozilla/webtools/tinderbox/doadmin.cgi b/mozilla/webtools/tinderbox/doadmin.cgi new file mode 100755 index 00000000000..25eea6148d1 --- /dev/null +++ b/mozilla/webtools/tinderbox/doadmin.cgi @@ -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\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 "

    Trimming Log files for $tree...

    \n

    "; + + $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 "
    $i Logfiles ( $k K bytes ) removed
    \n"; + + # + # Trim build.dat + # + $builds_removed = 0; + open(BD, "<$tree/build.dat"); + open(NBD, ">$tree/build.dat.new"); + while( ){ + ($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 "

    $builds_removed Builds removed from build.dat

    \n"; +} + +sub create_tree { + $treename = $form{'treename'}; + $modulename = $form{'modulename'}; + $branchname = $form{'branchname'}; + + if( -r $treename ){ + chmod 0777, $treename; + } + else { + mkdir( $treename, 0777 ) || die "

    Cannot mkdir $treename

    "; + } + 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 "

    Tree created or modified

    \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( ){ + ($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 "

    + $builds_removed Builds removed from build.dat

    \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 "

    + Message Changed

    \n"; +} + diff --git a/mozilla/webtools/tinderbox/ep_mac.pl b/mozilla/webtools/tinderbox/ep_mac.pl new file mode 100755 index 00000000000..dc1a723dc49 --- /dev/null +++ b/mozilla/webtools/tinderbox/ep_mac.pl @@ -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; +} diff --git a/mozilla/webtools/tinderbox/ep_unix.pl b/mozilla/webtools/tinderbox/ep_unix.pl new file mode 100755 index 00000000000..4308677d360 --- /dev/null +++ b/mozilla/webtools/tinderbox/ep_unix.pl @@ -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; +} diff --git a/mozilla/webtools/tinderbox/ep_windows.pl b/mozilla/webtools/tinderbox/ep_windows.pl new file mode 100755 index 00000000000..94832b7c358 --- /dev/null +++ b/mozilla/webtools/tinderbox/ep_windows.pl @@ -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; +} + diff --git a/mozilla/webtools/tinderbox/faq.html b/mozilla/webtools/tinderbox/faq.html new file mode 100755 index 00000000000..cc95e162317 --- /dev/null +++ b/mozilla/webtools/tinderbox/faq.html @@ -0,0 +1,31 @@ + + + + + + + + +

    +FAQ on Tinderbox 

    +Q. What is Tinderbox. +
    A. Your very own automated build page.  It shows you how builds +are going on various platforms. fs +
    +
    Q. I just checked in some code.  How can I tell when +I'm OK. +
    A. You name will appear in the guilty column.  +When there are successful (green) builds in +all the columns in a row above your name, you know you are ok. +
    +
    Q. The tree is broken, how do I find out what is busted +(or who busted it). +
    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. +
    +
    More Questions? Mail me ltabb@netscape.com +
    + + + diff --git a/mozilla/webtools/tinderbox/fixupimages.pl b/mozilla/webtools/tinderbox/fixupimages.pl new file mode 100755 index 00000000000..8c04dfd2350 --- /dev/null +++ b/mozilla/webtools/tinderbox/fixupimages.pl @@ -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( ){ + 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; +} diff --git a/mozilla/webtools/tinderbox/globals.pl b/mozilla/webtools/tinderbox/globals.pl new file mode 100755 index 00000000000..7ce5ad06cc1 --- /dev/null +++ b/mozilla/webtools/tinderbox/globals.pl @@ -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_tag = ""; +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( ){ + 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( ){ + $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
    \n"; + $i++; + } + + #for $i (@{$build_name_names}) { + # print "$build_name_names->[$i] $i
    \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 "

    warning: Couldn't open $t->{name}/notes.txt

    \n"; + while(){ + 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' $_
    "; + 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] .= + "
    \n[$nwho - $now_str]\n$note\n
    "; + } + } + 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, "; + 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 = ; + 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 "Invalid password; try again.
    "; + } + print " +
    +Password: +
    + If correct, remember password as a cookie
    +"; + + while (my ($key,$value) = each %form) { + if ($key eq "password" || $key eq "rememberpassword") { + next; + } + my $enc = value_encode($value); + print "\n"; + } + print "
    \n"; + exit; +} diff --git a/mozilla/webtools/tinderbox/handlemail.pl b/mozilla/webtools/tinderbox/handlemail.pl new file mode 100755 index 00000000000..c3e1222a75f --- /dev/null +++ b/mozilla/webtools/tinderbox/handlemail.pl @@ -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(){ + print DF $_; +} +close(DF); + +$err = system("./processbuild.pl data/tbx.$$"); + +if( $err ) { + die "processbuild.pl returned an error\n"; +} + diff --git a/mozilla/webtools/tinderbox/imagelog.pl b/mozilla/webtools/tinderbox/imagelog.pl new file mode 100755 index 00000000000..6127da320ee --- /dev/null +++ b/mozilla/webtools/tinderbox/imagelog.pl @@ -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 = ; + + # return a random line + srand; + @ret = split(/\`/,$log[rand @log]); + + close( IMAGELOG ); + @ret; +} + + diff --git a/mozilla/webtools/tinderbox/index.html b/mozilla/webtools/tinderbox/index.html new file mode 100755 index 00000000000..50643e48ef5 --- /dev/null +++ b/mozilla/webtools/tinderbox/index.html @@ -0,0 +1,12 @@ +tinderbox + + +
    +
    + +You're looking for +showbuilds.cgi. + +
    +
    diff --git a/mozilla/webtools/tinderbox/processbuild.pl b/mozilla/webtools/tinderbox/processbuild.pl new file mode 100755 index 00000000000..7fcd0f5df77 --- /dev/null +++ b/mozilla/webtools/tinderbox/processbuild.pl @@ -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 = ){ + chop($line); + if( $line =~ /^tinderbox\:/ ){ + if( $line =~ /^tinderbox\:[ \t]*([^:]*)\:[ \t]*([^\n]*)/ ){ + $tbx{$1} = $2; + } + } + } +} + +sub parse_mail_header { + while($line = ){ + 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 = ) ){ + 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 = ){ + 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] ); +} diff --git a/mozilla/webtools/tinderbox/reledanim.gif b/mozilla/webtools/tinderbox/reledanim.gif new file mode 100644 index 0000000000000000000000000000000000000000..2d6c9685191c2f4e06bb93aaf6f2012cddc5079b GIT binary patch literal 1685 zcmbu8YfzMB6vq#OiWb490V@}m7vw6aJZh#cBl>a^G+0;+N6clGM^REkkrd4kgatuZ zLGaB9LDVS*7$gLeF(Yw>dTc~dk&7ajB_*Rdd6}}e^X%uo^?W;f&iS9;`JZ>gB0?9v zr*j5pcmW{u$7ETOWh%==mVrl%$xM}{5C%9EsZk7}krJ^mhl5cYrBMr;fiJ{kd{mN% zBmv(K$6`dOM2SR!uZt9zBvc|qB7oZ?6xK>WB_I;udgupYVmI1>`y&Kyh}0;C&`61; z$bo}V8>LYTxN|&>F+M^ma3gU)9E%YllmPmQ>mmgvDG&v95@)YQ5yJ(cr~Um#s_#YG!pm2u^18H9|!l& z3A*hEYm9%HnwREV_qYf8zWvs^jv}|n@~o~?^B+w!UO4cw?dias%aIPsctMjBLGP{J zW{7|D_wX}YOcjf5b@~L&nRluuyr1@)snI7<3>sg!As`_ajBXuVuROAU-g67*`Ear3V!Kd?qVYs{kxxxJ})0uZ*@vI z5;KtY?4EeIa%^IiaI!|+`|jE)iw8FZRknGJSl$_2f1~nz!t=eoHj4D@TVJ%RgMNtd z-*(&e;+1{P$Nv81sPc8?-m>BiLAgFV_RzX#-k~SX`Ii}1SS{RT8=?)~d29cWYUgo% zy}J3t0iVa7r61VF9~;(a51KyLoObCg-R5;RzIx4mt;gNy^s}8#8y!^))neKHAz=!@MtPZ*?#jzh%mIB=rg`ckIfAlTaZy=;n!Q59Bg4> zzE|LX-m9u3d%|P&b(2npY{Zc3 zMb;14hi`~Ht?`L3^M0yNDk^T6aBa=Qt)@`YQPhexT*?O@5j-znig literal 0 HcmV?d00001 diff --git a/mozilla/webtools/tinderbox/showbuilds.cgi b/mozilla/webtools/tinderbox/showbuilds.cgi new file mode 100755 index 00000000000..e0063e9da8e --- /dev/null +++ b/mozilla/webtools/tinderbox/showbuilds.cgi @@ -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\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 "

    "; + print ""; + print "
    Select one of the following trees:
    \n"; + print "
      \n"; + + while(<*>) { + if( -d $_ && $_ ne 'data' && $_ ne 'CVS' ){ + print "
    • $_\n"; + } + } + print "
    "; +} + + + +sub display_page_head { + + my ($imageurl,$imagewidth,$imageheight,$quote) = &get_image; + + +# srand; +# $when = 60*10 + int rand(60*40); +# + + +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 ""; + print ""; + print "
    "; + print "


    "; + print "$quote

    "; + print "
    "; + print "

    "; + print "

    "; + print "
    "; + print "L = Show Build Log
    "; + print "L = Show Log comments
    "; + print "C = Show changes that occured since the last build
    "; + print "B = Download binary generated by the build
    "; + print ""; + print "
    Currently Building"; + print "
    Built successfully"; + print "
    Build failed"; + print "
    "; + print "
    "; + print "
    "; + + if( $form{'tree'} eq 'MercuryTip' || $form{'tree'} eq 'FreeSource'){ + print "

    The tree is currently "; + if( &tree_open ){ + print "OPEN"; + } + else { + print "CLOSED"; + } + print "\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 = ""; + } + + if ($build_time_times->[$t] % 7200 > 3600) { + $color = "white"; + } else { + $color = "beige"; + } + + print "\n"; + print "${qr}\n${tt}${er}\n"; + + + if( $tree2 ne "" ){ + print "\n"; + $qr = &query_ref( $td1, $build_time_times->[$t]); + print "${qr}X\n"; + } + + print "\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\n"; + } + + if( $tree2 ne "" ){ + print "\n"; + $qr = &query_ref( $td2, $build_time_times->[$t]); + print "${qr}X\n"; + + print "\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\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 "\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 "\n"; + + if( $hasnote ){ + print ""; + print "\n"; + } + print "\n"; + print "L\n"; + + #print "Build Summary
    \n"; + + if( $br->{previousbuildtime} ){ + $qr = &query_ref($br->{td}, $br->{previousbuildtime},$br->{buildtime}); + print "$qr\n"; + print " C\n"; + #print "What Changed
    \n"; + } + + if( $br->{binaryname} ne '' ){ + $binfile = "$buildtree/bin/$buildtime/$br->{buildname}/$br->{binaryname}"; + $binfile =~ s/ //g; + print " B"; + } + print "
    \n"; + + + } + } + else { + print " \n"; + } + $bn++; + } + + + print "\n"; +} + + +sub display_build_table_header { + local($i,$nspan); + + print "\n"; + + print "\n"; + print "\n"; + + + #print "\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
    /g; + $bn = "$bn"; + } + else { + $bn = "$bn"; + + } + + if( $t->{isbusted} ){ + print "\n"; + + print "\n"; + print "\n"; + +} + +sub display_build_table_footer { + print "
    Click time to
    see changes
    since time
    "; + $nspan = ( $tree2 ne "" ? 4 : 1); + print "
    Click name to see what they did"; + #print "Burning builds are busted"; + #print "
    "; + print "$bn\n"; + #print "\n"; + } + else { + print ""; + print "$bn\n"; + } + $i++; + } + print "
    Build Time\n"; + if( $tree2 ne "" ){ + print "$td1->{name}\n"; + print "$td2->{name}\n"; + } + else { + print "Guilty\n"; + } + print "
    \n"; + print "Show more checkin history

    \n"; + + if (open(FOOTER, "<$data_dir/footer.html")) { + while (