1*912701f9SAndroid Build Coastguard Worker#!/usr/bin/perl -w 2*912701f9SAndroid Build Coastguard Worker#--*-Perl-*-- 3*912701f9SAndroid Build Coastguard Worker 4*912701f9SAndroid Build Coastguard Worker# NOTES: 5*912701f9SAndroid Build Coastguard Worker# 6*912701f9SAndroid Build Coastguard Worker# 'tagscan' refers to the procedure of examining the CVS data (rlog output 7*912701f9SAndroid Build Coastguard Worker# for each file) and determining what bug IDs exist between two tags. 8*912701f9SAndroid Build Coastguard Worker# 9*912701f9SAndroid Build Coastguard Worker# 'dcuthelp' refers to the procedures of examining the CVS rlog cache 10*912701f9SAndroid Build Coastguard Worker# given a tag and a list of bugs, and helping to incorporate those bug 11*912701f9SAndroid Build Coastguard Worker# fixes into the tag. For this to occur, in each file, any changes after 12*912701f9SAndroid Build Coastguard Worker# tag within the bug list must be contiguous and must begin in the tag's 13*912701f9SAndroid Build Coastguard Worker# revision. 14*912701f9SAndroid Build Coastguard Worker# 15*912701f9SAndroid Build Coastguard Worker# Params: 16*912701f9SAndroid Build Coastguard Worker# debug - if set, output debugging info 17*912701f9SAndroid Build Coastguard Worker# user - user name 18*912701f9SAndroid Build Coastguard Worker# path_info - override actual path info, for debugging, e.g., "/form" 19*912701f9SAndroid Build Coastguard Worker# mod - module(s) list 20*912701f9SAndroid Build Coastguard Worker# include_attic - if set, include Attic during search (ignored by default) 21*912701f9SAndroid Build Coastguard Worker 22*912701f9SAndroid Build Coastguard Workeruse strict; 23*912701f9SAndroid Build Coastguard Workeruse CGI; 24*912701f9SAndroid Build Coastguard Worker#use CGI::Carp qw(fatalsToBrowser); # Do NOT use this -- doesn't work 25*912701f9SAndroid Build Coastguard Workeruse File::Path; 26*912701f9SAndroid Build Coastguard Workeruse IO::Handle; 27*912701f9SAndroid Build Coastguard Workeruse Time::Local 'timelocal_nocheck'; 28*912701f9SAndroid Build Coastguard Workeruse Carp; 29*912701f9SAndroid Build Coastguard Worker#use Data::Dumper; 30*912701f9SAndroid Build Coastguard Worker 31*912701f9SAndroid Build Coastguard Workeruse vars qw($QUERY $DEBUG $USER $TITLE $CLDR 32*912701f9SAndroid Build Coastguard Worker $DIFF_URL $DIFF_URL_SUFFIX $CVSWEB_REP_ID $CVSWEB_REP_SUFF $LOG_URL_SUFFIX $SHOW_URL $SHOW_URL_SUFFIX $LOG_URL 33*912701f9SAndroid Build Coastguard Worker $CVSROOT $BASE_REV %MOD_ABBREV $DEFAULT_MOD $NO_JITTERBUG 34*912701f9SAndroid Build Coastguard Worker $CACHE $INSTA $INSTA_ATTIC 35*912701f9SAndroid Build Coastguard Worker $UPDATE_COUNT $UPDATE_ATTIC_COUNT $UPDATE_NONATTIC_COUNT 36*912701f9SAndroid Build Coastguard Worker $TAGSCAN_TAG_LO $TAGSCAN_TAG_HI %TAGSCAN_IDS $TAGSCAN_COUNT 37*912701f9SAndroid Build Coastguard Worker $TAGSCAN_TAG_HI_DATE 38*912701f9SAndroid Build Coastguard Worker %TAGSCAN_ALLTAGS %TAGSCAN_WHY 39*912701f9SAndroid Build Coastguard Worker $DCUTHELP_TAG %DCUTHELP_IDS 40*912701f9SAndroid Build Coastguard Worker @DCUTHELP_BADFILES $DCUTHELP_COUNT @DCUTHELP_RETAGS 41*912701f9SAndroid Build Coastguard Worker @TAGLESS_FILES @BRANCHED_FILES @NO_JITTERBUG_FILES 42*912701f9SAndroid Build Coastguard Worker %MODE_MAP $NOW $YEAR $CVS_MSG_KW 43*912701f9SAndroid Build Coastguard Worker ); 44*912701f9SAndroid Build Coastguard Worker 45*912701f9SAndroid Build Coastguard Worker&initGlobals; 46*912701f9SAndroid Build Coastguard Worker&main; 47*912701f9SAndroid Build Coastguard Workerexit(0); 48*912701f9SAndroid Build Coastguard Worker 49*912701f9SAndroid Build Coastguard Worker#--------------------------------------------------------------------- 50*912701f9SAndroid Build Coastguard Workersub initGlobals() { 51*912701f9SAndroid Build Coastguard Worker $QUERY = new CGI; 52*912701f9SAndroid Build Coastguard Worker 53*912701f9SAndroid Build Coastguard Worker $DEBUG = $QUERY->param('debug'); 54*912701f9SAndroid Build Coastguard Worker $CLDR=1; 55*912701f9SAndroid Build Coastguard Worker 56*912701f9SAndroid Build Coastguard Worker # User name, if any. We try to propagate the user name so a logged-in 57*912701f9SAndroid Build Coastguard Worker # jitterbug user can stay that way. 58*912701f9SAndroid Build Coastguard Worker $USER = $QUERY->param('user'); 59*912701f9SAndroid Build Coastguard Worker 60*912701f9SAndroid Build Coastguard Worker $CVSWEB_REP_ID = "ICU"; 61*912701f9SAndroid Build Coastguard Worker 62*912701f9SAndroid Build Coastguard Worker if ($CLDR == 0) { 63*912701f9SAndroid Build Coastguard Worker $TITLE="ICU Jitterbug Diffs"; 64*912701f9SAndroid Build Coastguard Worker } else { 65*912701f9SAndroid Build Coastguard Worker $TITLE="CLDR Jitterbug Diffs"; 66*912701f9SAndroid Build Coastguard Worker } 67*912701f9SAndroid Build Coastguard Worker #$CVSWEB_REP_SUFF = "&cvsroot=" . $CVSWEB_REP_ID; 68*912701f9SAndroid Build Coastguard Worker $CVSWEB_REP_SUFF = ""; 69*912701f9SAndroid Build Coastguard Worker 70*912701f9SAndroid Build Coastguard Worker # The following URLs should be suffixed with a module name 71*912701f9SAndroid Build Coastguard Worker # such as "icu/icu". 72*912701f9SAndroid Build Coastguard Worker 73*912701f9SAndroid Build Coastguard Worker # Display the diffs between two revisions of a file 74*912701f9SAndroid Build Coastguard Worker # E.g., suffix with "/icu/icu/license.html.diff?r1=1.2&r2=1.3" 75*912701f9SAndroid Build Coastguard Worker $DIFF_URL = "http://www.unicode.org/cgi-bin/viewcvs.cgi"; # No trailing "/" 76*912701f9SAndroid Build Coastguard Worker $DIFF_URL_SUFFIX = $CVSWEB_REP_SUFF; 77*912701f9SAndroid Build Coastguard Worker 78*912701f9SAndroid Build Coastguard Worker # Display a specific file revision 79*912701f9SAndroid Build Coastguard Worker # E.g., suffix with "/icu/icu/license.html?rev=1.1$SHOW_URL_SUFFIX" 80*912701f9SAndroid Build Coastguard Worker $SHOW_URL = $DIFF_URL; # No trailing "/" 81*912701f9SAndroid Build Coastguard Worker $SHOW_URL_SUFFIX = "&content-type=text/x-cvsweb-markup" . $CVSWEB_REP_SUFF; 82*912701f9SAndroid Build Coastguard Worker 83*912701f9SAndroid Build Coastguard Worker # Display the CVS log for a file 84*912701f9SAndroid Build Coastguard Worker # E.g., suffix with "/icu/icu/license.html" 85*912701f9SAndroid Build Coastguard Worker $LOG_URL = $DIFF_URL; # No trailing "/" 86*912701f9SAndroid Build Coastguard Worker $LOG_URL_SUFFIX = $CVSWEB_REP_SUFF; 87*912701f9SAndroid Build Coastguard Worker 88*912701f9SAndroid Build Coastguard Worker # CVS root 89*912701f9SAndroid Build Coastguard Worker if ( $CLDR == 0 ) { 90*912701f9SAndroid Build Coastguard Worker $CVSROOT = "/data/mirrors/icu"; # Must NOT end with "/" 91*912701f9SAndroid Build Coastguard Worker } else { 92*912701f9SAndroid Build Coastguard Worker $CVSROOT = "/home/cvsroot"; 93*912701f9SAndroid Build Coastguard Worker } 94*912701f9SAndroid Build Coastguard Worker 95*912701f9SAndroid Build Coastguard Worker # A fake revision number indicating the slot before the oldest revision in 96*912701f9SAndroid Build Coastguard Worker # the rlog history. Not user visible. 97*912701f9SAndroid Build Coastguard Worker $BASE_REV = "0"; 98*912701f9SAndroid Build Coastguard Worker 99*912701f9SAndroid Build Coastguard Worker if ($CLDR == 0) { 100*912701f9SAndroid Build Coastguard Worker # Recognized abbreviated module names. 101*912701f9SAndroid Build Coastguard Worker %MOD_ABBREV = ( 102*912701f9SAndroid Build Coastguard Worker icu => 'icu', 103*912701f9SAndroid Build Coastguard Worker icuapps => 'icuapps', 104*912701f9SAndroid Build Coastguard Worker icu4j => 'icu4j', 105*912701f9SAndroid Build Coastguard Worker icu4jni => 'icu4jni', 106*912701f9SAndroid Build Coastguard Worker unicodetools => 'unicodetools', 107*912701f9SAndroid Build Coastguard Worker charset => 'charset', 108*912701f9SAndroid Build Coastguard Worker ); 109*912701f9SAndroid Build Coastguard Worker 110*912701f9SAndroid Build Coastguard Worker # Default modules to search 111*912701f9SAndroid Build Coastguard Worker $DEFAULT_MOD = 'icu icu4j'; 112*912701f9SAndroid Build Coastguard Worker } else { 113*912701f9SAndroid Build Coastguard Worker # Recognized abbreviated module names. 114*912701f9SAndroid Build Coastguard Worker %MOD_ABBREV = ( 115*912701f9SAndroid Build Coastguard Worker cldr => 'cldr', 116*912701f9SAndroid Build Coastguard Worker common => 'cldr/common', 117*912701f9SAndroid Build Coastguard Worker ); 118*912701f9SAndroid Build Coastguard Worker 119*912701f9SAndroid Build Coastguard Worker # Default modules to search 120*912701f9SAndroid Build Coastguard Worker $DEFAULT_MOD = 'common'; 121*912701f9SAndroid Build Coastguard Worker } 122*912701f9SAndroid Build Coastguard Worker 123*912701f9SAndroid Build Coastguard Worker 124*912701f9SAndroid Build Coastguard Worker # Magic Jitterbug ID used when a CVS checkin does not include a 125*912701f9SAndroid Build Coastguard Worker # Jitterbug ID. Should be unlikely (or impossible) to be a real 126*912701f9SAndroid Build Coastguard Worker # Jitterbug ID. 127*912701f9SAndroid Build Coastguard Worker $NO_JITTERBUG = 9999987; 128*912701f9SAndroid Build Coastguard Worker 129*912701f9SAndroid Build Coastguard Worker # Root of our cache of CVS meta-information. Right now this cache 130*912701f9SAndroid Build Coastguard Worker # takes the form of a mirror of /usr/cvs. We only mirror 131*912701f9SAndroid Build Coastguard Worker # /usr/cvs/icu/icu and /usr/cvs/icu4j/icu4j at this point. All CVS 132*912701f9SAndroid Build Coastguard Worker # files (*,v) have an identically named file in the same location in 133*912701f9SAndroid Build Coastguard Worker # the cache. Currently the cache file is the output of rlog. In the 134*912701f9SAndroid Build Coastguard Worker # future a more compressed form could be used (although there isn't 135*912701f9SAndroid Build Coastguard Worker # much to be gained, maybe 10%). Instead of grepping over the CVS 136*912701f9SAndroid Build Coastguard Worker # repository, we grep over the cache. This cuts the grep time by 137*912701f9SAndroid Build Coastguard Worker # about 90%. Before using the cache, we update it by walking through 138*912701f9SAndroid Build Coastguard Worker # the CVS repository and checking file mod dates. Any file that's 139*912701f9SAndroid Build Coastguard Worker # been changed gets updated in the cache. 140*912701f9SAndroid Build Coastguard Worker # Use real path; link causes problems. 141*912701f9SAndroid Build Coastguard Worker #$CACHE = "/www/software10/cgi-bin/icu/grepj.cache"; 142*912701f9SAndroid Build Coastguard Worker if($CLDR==0) { 143*912701f9SAndroid Build Coastguard Worker $CACHE = "/tmp/icu-grepj.cache"; # No trailing "/" 144*912701f9SAndroid Build Coastguard Worker } else { 145*912701f9SAndroid Build Coastguard Worker $CACHE = "/tmp/icu-grepj-cldr.cache"; # No trailing "/" 146*912701f9SAndroid Build Coastguard Worker } 147*912701f9SAndroid Build Coastguard Worker 148*912701f9SAndroid Build Coastguard Worker # Another cache that holds the results of the last searches. 149*912701f9SAndroid Build Coastguard Worker # Invalidate this cache whenever the main cache needs updating. 150*912701f9SAndroid Build Coastguard Worker # This cache consists of files named "1234". Each file 151*912701f9SAndroid Build Coastguard Worker # contains the final HTML for that bug ID. Searches that include 152*912701f9SAndroid Build Coastguard Worker # the attic are kept in a subdirectory 'Attic'. 153*912701f9SAndroid Build Coastguard Worker $INSTA = "$CACHE/insta"; 154*912701f9SAndroid Build Coastguard Worker $INSTA_ATTIC = "$INSTA/Attic"; 155*912701f9SAndroid Build Coastguard Worker 156*912701f9SAndroid Build Coastguard Worker # Count of updated cache files 157*912701f9SAndroid Build Coastguard Worker $UPDATE_COUNT = 0; 158*912701f9SAndroid Build Coastguard Worker $UPDATE_ATTIC_COUNT = 0; 159*912701f9SAndroid Build Coastguard Worker $UPDATE_NONATTIC_COUNT = 0; 160*912701f9SAndroid Build Coastguard Worker 161*912701f9SAndroid Build Coastguard Worker # Dispatch table mapping path_info to sub 162*912701f9SAndroid Build Coastguard Worker %MODE_MAP = ( 163*912701f9SAndroid Build Coastguard Worker '/top' => \&emit_top, 164*912701f9SAndroid Build Coastguard Worker '/form' => \&emit_form, 165*912701f9SAndroid Build Coastguard Worker '/difflist' => \&emit_difflist, 166*912701f9SAndroid Build Coastguard Worker '/nav' => \&emit_nav, 167*912701f9SAndroid Build Coastguard Worker '/result' => \&emit_result, 168*912701f9SAndroid Build Coastguard Worker '/help' => \&emit_help, 169*912701f9SAndroid Build Coastguard Worker '/admintop' => \&emit_admintop, 170*912701f9SAndroid Build Coastguard Worker '/adminform' => \&emit_adminform, 171*912701f9SAndroid Build Coastguard Worker '/adminresult' => \&emit_adminresult, 172*912701f9SAndroid Build Coastguard Worker '/localdiff' => \&emit_localdiff, 173*912701f9SAndroid Build Coastguard Worker ); 174*912701f9SAndroid Build Coastguard Worker 175*912701f9SAndroid Build Coastguard Worker $NOW = time(); 176*912701f9SAndroid Build Coastguard Worker $YEAR = 1900+@{[localtime]}[5]; # Get the current year 177*912701f9SAndroid Build Coastguard Worker 178*912701f9SAndroid Build Coastguard Worker # Regex for grepping for jitterbug checkin comments 179*912701f9SAndroid Build Coastguard Worker # Will be surrounded by parens 180*912701f9SAndroid Build Coastguard Worker if($CLDR == 0) { 181*912701f9SAndroid Build Coastguard Worker $CVS_MSG_KW = "jitterbug|fixed"; 182*912701f9SAndroid Build Coastguard Worker } else { 183*912701f9SAndroid Build Coastguard Worker $CVS_MSG_KW = "cldrbug"; 184*912701f9SAndroid Build Coastguard Worker } 185*912701f9SAndroid Build Coastguard Worker} 186*912701f9SAndroid Build Coastguard Worker 187*912701f9SAndroid Build Coastguard Worker#--------------------------------------------------------------------- 188*912701f9SAndroid Build Coastguard Worker# This script generates various frames within framesets. The 'mode' 189*912701f9SAndroid Build Coastguard Worker# parameter determines which frame is generated. 190*912701f9SAndroid Build Coastguard Workersub main() { 191*912701f9SAndroid Build Coastguard Worker 192*912701f9SAndroid Build Coastguard Worker STDOUT->autoflush(1); # Make progress output appear progressively... 193*912701f9SAndroid Build Coastguard Worker 194*912701f9SAndroid Build Coastguard Worker my $needed = 'h'; # next up: 'h'eader or 'e'nd_html 195*912701f9SAndroid Build Coastguard Worker 196*912701f9SAndroid Build Coastguard Worker eval { 197*912701f9SAndroid Build Coastguard Worker local $SIG{'__DIE__'}; # disable installed DIE hooks 198*912701f9SAndroid Build Coastguard Worker local $SIG{'__WARN__'} = sub { die $_[0]; }; # transmute warnings 199*912701f9SAndroid Build Coastguard Worker 200*912701f9SAndroid Build Coastguard Worker # The path info specifies what we are being called to emit. 201*912701f9SAndroid Build Coastguard Worker # This script emits the frameset and the frames within it 202*912701f9SAndroid Build Coastguard Worker # depending on this param. For the URL 203*912701f9SAndroid Build Coastguard Worker # "http://oss.software.ibm.com/cvs/icu-jinfo/foo", the path 204*912701f9SAndroid Build Coastguard Worker # info is "/foo". The path info can be overridden (for debugging) 205*912701f9SAndroid Build Coastguard Worker # with a CGI param of "path_info=/bar". 206*912701f9SAndroid Build Coastguard Worker my $path_info = $QUERY->path_info; 207*912701f9SAndroid Build Coastguard Worker if ($QUERY->param('path_info')) { 208*912701f9SAndroid Build Coastguard Worker $path_info = $QUERY->param('path_info'); 209*912701f9SAndroid Build Coastguard Worker } 210*912701f9SAndroid Build Coastguard Worker 211*912701f9SAndroid Build Coastguard Worker # Simplify it: "/foo/..." or "/foo&..." => "/foo" 212*912701f9SAndroid Build Coastguard Worker $path_info =~ s|(\w)\W.*|$1|; 213*912701f9SAndroid Build Coastguard Worker $path_info ||= '/top'; # default 214*912701f9SAndroid Build Coastguard Worker 215*912701f9SAndroid Build Coastguard Worker my $fn = $MODE_MAP{$path_info}; 216*912701f9SAndroid Build Coastguard Worker die "unknown path_info \"$path_info\"" unless ($fn); 217*912701f9SAndroid Build Coastguard Worker 218*912701f9SAndroid Build Coastguard Worker if ($path_info ne '/localdiff') { 219*912701f9SAndroid Build Coastguard Worker print $QUERY->header; 220*912701f9SAndroid Build Coastguard Worker $needed = 'e'; 221*912701f9SAndroid Build Coastguard Worker } 222*912701f9SAndroid Build Coastguard Worker 223*912701f9SAndroid Build Coastguard Worker $fn->(); 224*912701f9SAndroid Build Coastguard Worker }; 225*912701f9SAndroid Build Coastguard Worker 226*912701f9SAndroid Build Coastguard Worker if ($@) { 227*912701f9SAndroid Build Coastguard Worker if ($needed eq 'h') { 228*912701f9SAndroid Build Coastguard Worker print $QUERY->header; 229*912701f9SAndroid Build Coastguard Worker $needed = 'e'; 230*912701f9SAndroid Build Coastguard Worker } 231*912701f9SAndroid Build Coastguard Worker print "<hr><b>Internal error: ", $@, 232*912701f9SAndroid Build Coastguard Worker "<br>Please contact <a href=\"mailto:alanliu\@us.ibm.com\">Alan</a></b>"; 233*912701f9SAndroid Build Coastguard Worker } 234*912701f9SAndroid Build Coastguard Worker 235*912701f9SAndroid Build Coastguard Worker if ($needed eq 'e') { 236*912701f9SAndroid Build Coastguard Worker print $QUERY->end_html; 237*912701f9SAndroid Build Coastguard Worker } 238*912701f9SAndroid Build Coastguard Worker} 239*912701f9SAndroid Build Coastguard Worker 240*912701f9SAndroid Build Coastguard Worker#--------------------------------------------------------------------- 241*912701f9SAndroid Build Coastguard Worker# Create URL for the reviewer index 242*912701f9SAndroid Build Coastguard Worker# @param user (or empty string if none) 243*912701f9SAndroid Build Coastguard Workersub reviewersURL { 244*912701f9SAndroid Build Coastguard Worker my $user = shift || ''; 245*912701f9SAndroid Build Coastguard Worker $user = "?user=$user" if ($user); 246*912701f9SAndroid Build Coastguard Worker return "http://bugs.icu-project.org/cgibin/private/byname/review$user"; 247*912701f9SAndroid Build Coastguard Worker} 248*912701f9SAndroid Build Coastguard Worker 249*912701f9SAndroid Build Coastguard Worker#--------------------------------------------------------------------- 250*912701f9SAndroid Build Coastguard Worker# Create URL for jitterbug 251*912701f9SAndroid Build Coastguard Worker# @param user (or empty string if none) 252*912701f9SAndroid Build Coastguard Worker# @param ID (or empty if none); 253*912701f9SAndroid Build Coastguard Workersub jitterbugURL { 254*912701f9SAndroid Build Coastguard Worker my $user = shift || ''; 255*912701f9SAndroid Build Coastguard Worker my $id = shift || ''; 256*912701f9SAndroid Build Coastguard Worker 257*912701f9SAndroid Build Coastguard Worker if($CLDR == 0) { 258*912701f9SAndroid Build Coastguard Worker if ($id ne '') { 259*912701f9SAndroid Build Coastguard Worker if ($user) { 260*912701f9SAndroid Build Coastguard Worker return "http://bugs.icu-project.org/cgibin/private/icu-bugs-private?;user=$user;findid=$id"; 261*912701f9SAndroid Build Coastguard Worker } else { 262*912701f9SAndroid Build Coastguard Worker return "http://bugs.icu-project.org/cgibin/icu-bugs?findid=$id"; 263*912701f9SAndroid Build Coastguard Worker } 264*912701f9SAndroid Build Coastguard Worker } else { 265*912701f9SAndroid Build Coastguard Worker if ($user) { 266*912701f9SAndroid Build Coastguard Worker return "http://bugs.icu-project.org/cgibin/private/icu-bugs-private?;user=$user;"; 267*912701f9SAndroid Build Coastguard Worker } else { 268*912701f9SAndroid Build Coastguard Worker return "http://bugs.icu-project.org/cgibin/icu-bugs"; 269*912701f9SAndroid Build Coastguard Worker } 270*912701f9SAndroid Build Coastguard Worker } 271*912701f9SAndroid Build Coastguard Worker } else { 272*912701f9SAndroid Build Coastguard Worker if ($id ne '') { 273*912701f9SAndroid Build Coastguard Worker if ($user) { 274*912701f9SAndroid Build Coastguard Worker return "http://bugs.icu-project.org/cgibin/cldr/locale-bugs-private?;user=$user;findid=$id"; 275*912701f9SAndroid Build Coastguard Worker } else { 276*912701f9SAndroid Build Coastguard Worker return "http://bugs.icu-project.org/cgibin/locale-bugs?findid=$id"; 277*912701f9SAndroid Build Coastguard Worker } 278*912701f9SAndroid Build Coastguard Worker } else { 279*912701f9SAndroid Build Coastguard Worker if ($user) { 280*912701f9SAndroid Build Coastguard Worker return "http://bugs.icu-project.org/cgibin/cldr/locale-bugs-private?;user=$user;"; 281*912701f9SAndroid Build Coastguard Worker } else { 282*912701f9SAndroid Build Coastguard Worker return "http://bugs.icu-project.org/cgibin/locale-bugs"; 283*912701f9SAndroid Build Coastguard Worker } 284*912701f9SAndroid Build Coastguard Worker } 285*912701f9SAndroid Build Coastguard Worker } 286*912701f9SAndroid Build Coastguard Worker} 287*912701f9SAndroid Build Coastguard Worker 288*912701f9SAndroid Build Coastguard Worker###################################################################### 289*912701f9SAndroid Build Coastguard Worker# HTML GUI 290*912701f9SAndroid Build Coastguard Worker###################################################################### 291*912701f9SAndroid Build Coastguard Worker 292*912701f9SAndroid Build Coastguard Worker# Emit the HTML for the top frameset in normal (bug diffs) mode 293*912701f9SAndroid Build Coastguard Workersub emit_top { 294*912701f9SAndroid Build Coastguard Worker # Propagate url parameters down to the frames within the frameset 295*912701f9SAndroid Build Coastguard Worker 296*912701f9SAndroid Build Coastguard Worker my $self = $QUERY->url(-full=>1, -query=>1); 297*912701f9SAndroid Build Coastguard Worker my $f = urlPathInfo($self, '/form'); 298*912701f9SAndroid Build Coastguard Worker my $dl = urlPathInfo($self, '/difflist'); 299*912701f9SAndroid Build Coastguard Worker my $n = urlPathInfo($self, '/nav'); 300*912701f9SAndroid Build Coastguard Worker my $r = urlPathInfo($self, '/result'); 301*912701f9SAndroid Build Coastguard Worker 302*912701f9SAndroid Build Coastguard Worker print <<END; 303*912701f9SAndroid Build Coastguard Worker<html><head><title>$TITLE</title></head> 304*912701f9SAndroid Build Coastguard Worker<!--$self--> 305*912701f9SAndroid Build Coastguard Worker<frameset cols="300,*"> 306*912701f9SAndroid Build Coastguard Worker <frameset rows="135,*"> 307*912701f9SAndroid Build Coastguard Worker <frame src="$f" name="form" scrolling=no> 308*912701f9SAndroid Build Coastguard Worker <frame src="$dl" name="difflist"> 309*912701f9SAndroid Build Coastguard Worker </frameset> 310*912701f9SAndroid Build Coastguard Worker <frame src="$r" name="result"> 311*912701f9SAndroid Build Coastguard Worker</frameset> 312*912701f9SAndroid Build Coastguard WorkerEND 313*912701f9SAndroid Build Coastguard Worker 314*912701f9SAndroid Build Coastguard Worker# <frameset rows="30,*"> 315*912701f9SAndroid Build Coastguard Worker# <frame src="$n" name="nav" scrolling=no> 316*912701f9SAndroid Build Coastguard Worker# <frame src="$r" name="result"> 317*912701f9SAndroid Build Coastguard Worker# </frameset> 318*912701f9SAndroid Build Coastguard Worker} 319*912701f9SAndroid Build Coastguard Worker 320*912701f9SAndroid Build Coastguard Workersub emit_form { 321*912701f9SAndroid Build Coastguard Worker print $QUERY->start_html(-title=>$TITLE, 322*912701f9SAndroid Build Coastguard Worker -target=>'difflist'); 323*912701f9SAndroid Build Coastguard Worker 324*912701f9SAndroid Build Coastguard Worker my $script_name = $QUERY->script_name; 325*912701f9SAndroid Build Coastguard Worker 326*912701f9SAndroid Build Coastguard Worker print $QUERY->startform(-action=>urlPathInfo($script_name, '/difflist'), 327*912701f9SAndroid Build Coastguard Worker -target=>'difflist', 328*912701f9SAndroid Build Coastguard Worker -method=>'GET'); 329*912701f9SAndroid Build Coastguard Worker 330*912701f9SAndroid Build Coastguard Worker my $user = $QUERY->param('user') || ''; 331*912701f9SAndroid Build Coastguard Worker 332*912701f9SAndroid Build Coastguard Worker print "<H2>$TITLE"; # h1 too big 333*912701f9SAndroid Build Coastguard Worker print " <FONT SIZE=-1>($user)</FONT>" if ($user); 334*912701f9SAndroid Build Coastguard Worker print "</H2>"; 335*912701f9SAndroid Build Coastguard Worker 336*912701f9SAndroid Build Coastguard Worker print "ID? ",$QUERY->textfield(-name=>'id',-size=>5) 337*912701f9SAndroid Build Coastguard Worker , $QUERY->submit(-name=>'Search') 338*912701f9SAndroid Build Coastguard Worker , " <FONT SIZE=-1><A href=\"" 339*912701f9SAndroid Build Coastguard Worker , urlPathInfo($script_name, '/help') 340*912701f9SAndroid Build Coastguard Worker , "\">Help</A></FONT>"; 341*912701f9SAndroid Build Coastguard Worker 342*912701f9SAndroid Build Coastguard Worker print "\ <FONT SIZE=-1>" 343*912701f9SAndroid Build Coastguard Worker , "<A href=\"", urlPathInfo($script_name, '/admintop') 344*912701f9SAndroid Build Coastguard Worker , "?user=$user\" target=\"_top\">Admin</A></FONT>"; 345*912701f9SAndroid Build Coastguard Worker 346*912701f9SAndroid Build Coastguard Worker print "<BR>\nModules: "; 347*912701f9SAndroid Build Coastguard Worker print $QUERY->textfield(-name=>'mod', 348*912701f9SAndroid Build Coastguard Worker -default=>$DEFAULT_MOD, 349*912701f9SAndroid Build Coastguard Worker -size=>30); 350*912701f9SAndroid Build Coastguard Worker 351*912701f9SAndroid Build Coastguard Worker print "<BR>\n"; 352*912701f9SAndroid Build Coastguard Worker 353*912701f9SAndroid Build Coastguard Worker print "<FONT SIZE=-1>"; 354*912701f9SAndroid Build Coastguard Worker print $QUERY->checkbox(-name=>"include_attic", 355*912701f9SAndroid Build Coastguard Worker -label=>"Incl. Attic"); 356*912701f9SAndroid Build Coastguard Worker print $QUERY->checkbox(-name=>"localdiff", 357*912701f9SAndroid Build Coastguard Worker -label=>"Local Diff"); 358*912701f9SAndroid Build Coastguard Worker print "</FONT>"; 359*912701f9SAndroid Build Coastguard Worker 360*912701f9SAndroid Build Coastguard Worker print "\ <A href=\"", reviewersURL($user), "\" target=\"_top\" title=\"List bugs by reviewer\">Reviewers</A>"; 361*912701f9SAndroid Build Coastguard Worker 362*912701f9SAndroid Build Coastguard Worker print "\ <A href=\"", jitterbugURL($user), "\" target=\"_top\" title=\"Go to main Jitterbug page\">Jitterbug</A>"; 363*912701f9SAndroid Build Coastguard Worker 364*912701f9SAndroid Build Coastguard Worker # Propagate params that don't have corresponding form elements 365*912701f9SAndroid Build Coastguard Worker print $QUERY->hidden('user'); 366*912701f9SAndroid Build Coastguard Worker print $QUERY->hidden('debug'); 367*912701f9SAndroid Build Coastguard Worker if($CLDR==1) { 368*912701f9SAndroid Build Coastguard Worker print $QUERY->hidden('cldr'); 369*912701f9SAndroid Build Coastguard Worker } 370*912701f9SAndroid Build Coastguard Worker 371*912701f9SAndroid Build Coastguard Worker print $QUERY->end_form; 372*912701f9SAndroid Build Coastguard Worker} 373*912701f9SAndroid Build Coastguard Worker 374*912701f9SAndroid Build Coastguard Workersub emit_nav { 375*912701f9SAndroid Build Coastguard Worker print $QUERY->start_html(-title=>$TITLE, 376*912701f9SAndroid Build Coastguard Worker -target=>'result'); 377*912701f9SAndroid Build Coastguard Worker print "Under construction: Navigation bar goes here"; 378*912701f9SAndroid Build Coastguard Worker} 379*912701f9SAndroid Build Coastguard Worker 380*912701f9SAndroid Build Coastguard Workersub emit_difflist { 381*912701f9SAndroid Build Coastguard Worker print $QUERY->start_html(-title=>$TITLE, 382*912701f9SAndroid Build Coastguard Worker -target=>'result'); 383*912701f9SAndroid Build Coastguard Worker 384*912701f9SAndroid Build Coastguard Worker ############################################################ 385*912701f9SAndroid Build Coastguard Worker # ID 386*912701f9SAndroid Build Coastguard Worker 387*912701f9SAndroid Build Coastguard Worker my $ID = $QUERY->param('id') || ''; 388*912701f9SAndroid Build Coastguard Worker $ID =~ s/\s//g; 389*912701f9SAndroid Build Coastguard Worker 390*912701f9SAndroid Build Coastguard Worker #print "<br/><b>query:</b>"; 391*912701f9SAndroid Build Coastguard Worker #print $QUERY->Dump; 392*912701f9SAndroid Build Coastguard Worker #print "<br/>"; 393*912701f9SAndroid Build Coastguard Worker 394*912701f9SAndroid Build Coastguard Worker if ($ID eq '') { 395*912701f9SAndroid Build Coastguard Worker print "(Warning: search, but No ID given.)<br/> \n"; 396*912701f9SAndroid Build Coastguard Worker &emit_help; 397*912701f9SAndroid Build Coastguard Worker return; 398*912701f9SAndroid Build Coastguard Worker } 399*912701f9SAndroid Build Coastguard Worker 400*912701f9SAndroid Build Coastguard Worker if ($ID =~ /^0*(\d+)$/) { 401*912701f9SAndroid Build Coastguard Worker $ID = $1; 402*912701f9SAndroid Build Coastguard Worker } else { 403*912701f9SAndroid Build Coastguard Worker print "\"$ID\" is not a valid Jitterbug ID. Please "; 404*912701f9SAndroid Build Coastguard Worker print "enter one or more decimal digits."; 405*912701f9SAndroid Build Coastguard Worker return; 406*912701f9SAndroid Build Coastguard Worker } 407*912701f9SAndroid Build Coastguard Worker 408*912701f9SAndroid Build Coastguard Worker ############################################################ 409*912701f9SAndroid Build Coastguard Worker # User 410*912701f9SAndroid Build Coastguard Worker 411*912701f9SAndroid Build Coastguard Worker my $user = $QUERY->param('user'); 412*912701f9SAndroid Build Coastguard Worker 413*912701f9SAndroid Build Coastguard Worker ############################################################ 414*912701f9SAndroid Build Coastguard Worker # Modules 415*912701f9SAndroid Build Coastguard Worker 416*912701f9SAndroid Build Coastguard Worker my @m; 417*912701f9SAndroid Build Coastguard Worker return if (!parseMod(\@m)); # what modules are we searching? 418*912701f9SAndroid Build Coastguard Worker 419*912701f9SAndroid Build Coastguard Worker my $localDiff = $QUERY->param('localdiff'); 420*912701f9SAndroid Build Coastguard Worker 421*912701f9SAndroid Build Coastguard Worker # Only use the INSTA cache for standard module searches. 422*912701f9SAndroid Build Coastguard Worker my $isStd = (join(' ', sort @m) eq 'icu/icu icu4j/icu4j') 423*912701f9SAndroid Build Coastguard Worker && !$localDiff; 424*912701f9SAndroid Build Coastguard Worker 425*912701f9SAndroid Build Coastguard Worker ############################################################ 426*912701f9SAndroid Build Coastguard Worker # Output 427*912701f9SAndroid Build Coastguard Worker 428*912701f9SAndroid Build Coastguard Worker print "What is Jitterbug ", jitterbugLink($user, $ID), "?"; 429*912701f9SAndroid Build Coastguard Worker 430*912701f9SAndroid Build Coastguard Worker foreach (@m) { 431*912701f9SAndroid Build Coastguard Worker updateCacheDir($_); 432*912701f9SAndroid Build Coastguard Worker } 433*912701f9SAndroid Build Coastguard Worker 434*912701f9SAndroid Build Coastguard Worker # If the cache has been updated then the instaCache entries 435*912701f9SAndroid Build Coastguard Worker # are all invalid and must be deleted. Otherwise try to 436*912701f9SAndroid Build Coastguard Worker # look up the diffs from the instaCache. 437*912701f9SAndroid Build Coastguard Worker mkpath($INSTA_ATTIC, 0, 0777); 438*912701f9SAndroid Build Coastguard Worker if ($UPDATE_COUNT) { 439*912701f9SAndroid Build Coastguard Worker print "done ($UPDATE_NONATTIC_COUNT,$UPDATE_ATTIC_COUNT)."; 440*912701f9SAndroid Build Coastguard Worker resetInstaCache(0); 441*912701f9SAndroid Build Coastguard Worker } elsif ($isStd) { 442*912701f9SAndroid Build Coastguard Worker my $diffs = instaGet($ID); 443*912701f9SAndroid Build Coastguard Worker if ($diffs) { 444*912701f9SAndroid Build Coastguard Worker print $diffs; 445*912701f9SAndroid Build Coastguard Worker print "<BR><EM><FONT SIZE=-1>(Results from cache)</FONT></EM>"; 446*912701f9SAndroid Build Coastguard Worker return; 447*912701f9SAndroid Build Coastguard Worker } 448*912701f9SAndroid Build Coastguard Worker } 449*912701f9SAndroid Build Coastguard Worker 450*912701f9SAndroid Build Coastguard Worker # If we don't find the ID in the instaCache, then generate 451*912701f9SAndroid Build Coastguard Worker # the diffs the hard way and store the result in the 452*912701f9SAndroid Build Coastguard Worker # instaCache. 453*912701f9SAndroid Build Coastguard Worker my $diffs; 454*912701f9SAndroid Build Coastguard Worker foreach my $module (@m) { 455*912701f9SAndroid Build Coastguard Worker debugOut("module $module") if ($DEBUG); 456*912701f9SAndroid Build Coastguard Worker my $m = $module; 457*912701f9SAndroid Build Coastguard Worker $m =~ s|^.+/||; 458*912701f9SAndroid Build Coastguard Worker $diffs .= out("<HR><CENTER><B><FONT SIZE=+1>", uc($m), 459*912701f9SAndroid Build Coastguard Worker "</FONT></B></CENTER><HR>"); 460*912701f9SAndroid Build Coastguard Worker debugOut("+generateDiffsList($ID, $module)") if ($DEBUG); 461*912701f9SAndroid Build Coastguard Worker $diffs .= generateDiffsList($ID, $module); 462*912701f9SAndroid Build Coastguard Worker debugOut("-generateDiffsList($ID, $module)") if ($DEBUG); 463*912701f9SAndroid Build Coastguard Worker } 464*912701f9SAndroid Build Coastguard Worker instaPut($ID, $diffs) if ($isStd); 465*912701f9SAndroid Build Coastguard Worker} 466*912701f9SAndroid Build Coastguard Worker 467*912701f9SAndroid Build Coastguard Workersub emit_localdiff { 468*912701f9SAndroid Build Coastguard Worker print $QUERY->header(-type=>'application/octet-stream', 469*912701f9SAndroid Build Coastguard Worker -attachment=>'localdiff.bat'); 470*912701f9SAndroid Build Coastguard Worker my $file = $QUERY->param('file'); 471*912701f9SAndroid Build Coastguard Worker my $r1 = $QUERY->param('r1'); 472*912701f9SAndroid Build Coastguard Worker my $r2 = $QUERY->param('r2'); 473*912701f9SAndroid Build Coastguard Worker my $mod = $QUERY->param('m'); 474*912701f9SAndroid Build Coastguard Worker my $leaf = $file; 475*912701f9SAndroid Build Coastguard Worker $leaf =~ s|.*[/\\]([^/\\]+)+$|$1|; 476*912701f9SAndroid Build Coastguard Worker $file = "$mod/$file"; 477*912701f9SAndroid Build Coastguard Worker my $eol = "\015\012"; # DOS eol 478*912701f9SAndroid Build Coastguard Worker print "cd %TEMP%$eol"; 479*912701f9SAndroid Build Coastguard Worker print "mkdir grepj$eol"; 480*912701f9SAndroid Build Coastguard Worker print "cd grepj$eol"; 481*912701f9SAndroid Build Coastguard Worker print "set CVSROOT=:pserver:$USER\@oss.software.ibm.com:/usr/cvs/$mod$eol"; 482*912701f9SAndroid Build Coastguard Worker print "cvs checkout -p -r $r1 $file > $leaf-$r1$eol"; 483*912701f9SAndroid Build Coastguard Worker print "cvs checkout -p -r $r2 $file > $leaf-$r2$eol"; 484*912701f9SAndroid Build Coastguard Worker print "start wincmp $leaf-$r1 $leaf-$r2$eol"; 485*912701f9SAndroid Build Coastguard Worker print "del \%0$eol"; 486*912701f9SAndroid Build Coastguard Worker} 487*912701f9SAndroid Build Coastguard Worker 488*912701f9SAndroid Build Coastguard Workersub emit_result { 489*912701f9SAndroid Build Coastguard Worker print $QUERY->start_html(-title=>$TITLE); 490*912701f9SAndroid Build Coastguard Worker} 491*912701f9SAndroid Build Coastguard Worker 492*912701f9SAndroid Build Coastguard Workersub emit_help { 493*912701f9SAndroid Build Coastguard Worker my $x = join(" ", sort keys(%MOD_ABBREV)); 494*912701f9SAndroid Build Coastguard Worker print <<END; 495*912701f9SAndroid Build Coastguard WorkerSearch the ICU and ICU4J CVS repositories for changes committed against 496*912701f9SAndroid Build Coastguard Workera specific Jitterbug. 497*912701f9SAndroid Build Coastguard Worker 498*912701f9SAndroid Build Coastguard Worker<P>For a change to be recognized, 499*912701f9SAndroid Build Coastguard Workerits commit comment must start with "<CODE>Jitterbug <B>n</B></CODE>", 500*912701f9SAndroid Build Coastguard Workerwhere <CODE><B>n</B></CODE> is the bug ID. 501*912701f9SAndroid Build Coastguard Worker 502*912701f9SAndroid Build Coastguard Worker<P>The search generates a list of all files changes for this bug, 503*912701f9SAndroid Build Coastguard Workertogether with the specific revisions in each 504*912701f9SAndroid Build Coastguard Workerfile that are relevant (there may be more than one). 505*912701f9SAndroid Build Coastguard Worker 506*912701f9SAndroid Build Coastguard Worker<P>In the diff list, 507*912701f9SAndroid Build Coastguard Workerselect a <B>file name link</B> to see the CVS log 508*912701f9SAndroid Build Coastguard Workerfor that file. 509*912701f9SAndroid Build Coastguard Worker 510*912701f9SAndroid Build Coastguard Worker<P>Select a <B>revision link</B> to see changes 511*912701f9SAndroid Build Coastguard Workerchecked in against that revision. "Diff" revision links 512*912701f9SAndroid Build Coastguard Workershow diffs against the previous revision. "View" links 513*912701f9SAndroid Build Coastguard Workershow initial check in revisions. 514*912701f9SAndroid Build Coastguard Worker 515*912701f9SAndroid Build Coastguard Worker<P>If a file contains more than one revision relevant to this 516*912701f9SAndroid Build Coastguard WorkerJitterbug ID, then an <B>overall revision link</B> will be available. 517*912701f9SAndroid Build Coastguard WorkerUse this to see the effect of all changes at once. <I>If the revisions 518*912701f9SAndroid Build Coastguard Workerare not contiguous, then this diff will contain changes 519*912701f9SAndroid Build Coastguard Workernot related to this Jitterbug.</I> In that case you may 520*912701f9SAndroid Build Coastguard Workerprefer to view the individual diffs instead. 521*912701f9SAndroid Build Coastguard Worker 522*912701f9SAndroid Build Coastguard Worker<P><B>Incl. Attic</B> causes files under any directory named 523*912701f9SAndroid Build Coastguard Worker"Attic" to be included. 524*912701f9SAndroid Build Coastguard Worker 525*912701f9SAndroid Build Coastguard Worker<P><B>Local Diff</B> enables special links that look like this [*] 526*912701f9SAndroid Build Coastguard Workerwhich cause your browser to download a Windows batch file. The 527*912701f9SAndroid Build Coastguard Workerbatch file, when executed, will bring up the relevant diffs in 528*912701f9SAndroid Build Coastguard WorkerCompare It!. For this to work, you need the following: 529*912701f9SAndroid Build Coastguard Worker 530*912701f9SAndroid Build Coastguard Worker<UL><LI><B>cvs</B> must be on your PATH. For example, you may 531*912701f9SAndroid Build Coastguard Workeradd <CODE>C:\\Program Files\\GNU\\WinCVS 1.2</CODE> to your PATH. 532*912701f9SAndroid Build Coastguard Worker<LI><B>wincmp</B> must be on your PATH. This is the Compare It! 533*912701f9SAndroid Build Coastguard Workerexecutable. For example, you may add <CODE>C:\\Program Files\\Compare 534*912701f9SAndroid Build Coastguard WorkerIt!</CODE> to your PATH. 535*912701f9SAndroid Build Coastguard Worker<LI>You must be "logged in" for the cvs checkouts to work. If your 536*912701f9SAndroid Build Coastguard Workername is present in parentheses next to "ICU Jitterbug Diffs" in the 537*912701f9SAndroid Build Coastguard Workerupper left frame, you are logged in. 538*912701f9SAndroid Build Coastguard Worker</UL> 539*912701f9SAndroid Build Coastguard Worker 540*912701f9SAndroid Build Coastguard Worker<P><B>Modules</B> lists the modules to be searched. By default 541*912701f9SAndroid Build Coastguard Workerthis is "icu icu4j" but any modules (under /usr/cvs) may be listed. 542*912701f9SAndroid Build Coastguard WorkerFull module names (e.g., "icu/icuapps") may be used. The following 543*912701f9SAndroid Build Coastguard Workerabbreviations are recognized: <CODE>$x</CODE>. 544*912701f9SAndroid Build Coastguard WorkerEND 545*912701f9SAndroid Build Coastguard Worker} 546*912701f9SAndroid Build Coastguard Worker 547*912701f9SAndroid Build Coastguard Worker###################################################################### 548*912701f9SAndroid Build Coastguard Worker# Admin GUI 549*912701f9SAndroid Build Coastguard Worker###################################################################### 550*912701f9SAndroid Build Coastguard Worker 551*912701f9SAndroid Build Coastguard Worker# Emit the HTML for the top frameset in admin mode 552*912701f9SAndroid Build Coastguard Workersub emit_admintop { 553*912701f9SAndroid Build Coastguard Worker # Propagate url parameters down to the frames within the frameset 554*912701f9SAndroid Build Coastguard Worker 555*912701f9SAndroid Build Coastguard Worker my $self = $QUERY->url(-full=>1, -query=>1); 556*912701f9SAndroid Build Coastguard Worker my $f = urlPathInfo($self, '/adminform'); 557*912701f9SAndroid Build Coastguard Worker my $r = urlPathInfo($self, '/adminresult'); 558*912701f9SAndroid Build Coastguard Worker my $TITLETXT = $TITLE; 559*912701f9SAndroid Build Coastguard Worker 560*912701f9SAndroid Build Coastguard Worker #if ($id ne '') { 561*912701f9SAndroid Build Coastguard Worker#`h TITLETXT = "$id - $TITLETXT"; 562*912701f9SAndroid Build Coastguard Worker # } 563*912701f9SAndroid Build Coastguard Worker 564*912701f9SAndroid Build Coastguard Worker print <<END; 565*912701f9SAndroid Build Coastguard Worker<html><head><title>$TITLE</title></head> 566*912701f9SAndroid Build Coastguard Worker<frameset cols="300,*"> 567*912701f9SAndroid Build Coastguard Worker <frame src="$f" name="adminform" scrolling=yes> 568*912701f9SAndroid Build Coastguard Worker <frame src="$r" name="adminresult"> 569*912701f9SAndroid Build Coastguard Worker</frameset> 570*912701f9SAndroid Build Coastguard WorkerEND 571*912701f9SAndroid Build Coastguard Worker} 572*912701f9SAndroid Build Coastguard Worker 573*912701f9SAndroid Build Coastguard Worker# Print the admin input form. 574*912701f9SAndroid Build Coastguard Workersub emit_adminform { 575*912701f9SAndroid Build Coastguard Worker 576*912701f9SAndroid Build Coastguard Worker print $QUERY->start_html(-title=>$TITLE, 577*912701f9SAndroid Build Coastguard Worker -target=>'adminresult'); 578*912701f9SAndroid Build Coastguard Worker 579*912701f9SAndroid Build Coastguard Worker my $script_name = $QUERY->script_name; 580*912701f9SAndroid Build Coastguard Worker 581*912701f9SAndroid Build Coastguard Worker print $QUERY->startform(-action=>urlPathInfo($script_name, '/adminresult'), 582*912701f9SAndroid Build Coastguard Worker -TARGET=>'adminresult'); 583*912701f9SAndroid Build Coastguard Worker 584*912701f9SAndroid Build Coastguard Worker print "<FONT SIZE=+2><B>Administrative Tools</B></FONT>"; 585*912701f9SAndroid Build Coastguard Worker 586*912701f9SAndroid Build Coastguard Worker my $user = $QUERY->param('user'); 587*912701f9SAndroid Build Coastguard Worker my $u = $user ? "?user=$user" : ''; 588*912701f9SAndroid Build Coastguard Worker print "\ <FONT SIZE=-1>" 589*912701f9SAndroid Build Coastguard Worker , "<A href=\"$script_name$u\" target=\"_top\">Back</A></FONT><BR>"; 590*912701f9SAndroid Build Coastguard Worker 591*912701f9SAndroid Build Coastguard Worker print '<FONT SIZE=-1>Tags may be specified in full, e.g. ' 592*912701f9SAndroid Build Coastguard Worker , '"release-2-4", or as release numbers, such as "2.4". ', 593*912701f9SAndroid Build Coastguard Worker 'Specify module(s) here for commands below.', 594*912701f9SAndroid Build Coastguard Worker '</FONT><BR>'; 595*912701f9SAndroid Build Coastguard Worker 596*912701f9SAndroid Build Coastguard Worker print "Modules: "; 597*912701f9SAndroid Build Coastguard Worker print $QUERY->textfield(-name=>'mod', 598*912701f9SAndroid Build Coastguard Worker -default=>$DEFAULT_MOD, 599*912701f9SAndroid Build Coastguard Worker -size=>30); 600*912701f9SAndroid Build Coastguard Worker print "<HR>"; 601*912701f9SAndroid Build Coastguard Worker 602*912701f9SAndroid Build Coastguard Worker print "<B>List Bugs Between CVS Tags</B><BR>"; 603*912701f9SAndroid Build Coastguard Worker print "<TABLE><TR><TD nowrap>Start Tag:</TD><TD>"; 604*912701f9SAndroid Build Coastguard Worker print $QUERY->textfield(-name=>'tag_lo',-size=>30); 605*912701f9SAndroid Build Coastguard Worker print "</TD></TR><TR><TD nowrap>End Tag:</TD><TD>"; 606*912701f9SAndroid Build Coastguard Worker print $QUERY->textfield(-name=>'tag_hi',-size=>30); 607*912701f9SAndroid Build Coastguard Worker print "</TD></TR><TR><TD></TD><TD>"; 608*912701f9SAndroid Build Coastguard Worker print $QUERY->submit(-name=>'Find Bugs'); 609*912701f9SAndroid Build Coastguard Worker print "</TD></TR></TABLE>"; 610*912701f9SAndroid Build Coastguard Worker print '<FONT SIZE=-1>Bugs are listed that occur after the start tag, up to and including the end tag. Specify module(s) above.</FONT>'; 611*912701f9SAndroid Build Coastguard Worker 612*912701f9SAndroid Build Coastguard Worker print "<HR>\n"; 613*912701f9SAndroid Build Coastguard Worker 614*912701f9SAndroid Build Coastguard Worker print "<B>DCUT Helper</B><BR>"; 615*912701f9SAndroid Build Coastguard Worker print "<TABLE><TR><TD>Tag:</TD><TD>"; 616*912701f9SAndroid Build Coastguard Worker print $QUERY->textfield(-name=>'dcut_tag',-size=>33); 617*912701f9SAndroid Build Coastguard Worker print "</TD></TR><TR VALIGN=TOP><TD>Bug IDs:</TD><TD>"; 618*912701f9SAndroid Build Coastguard Worker print $QUERY->textarea(-name=>'dcut_ids',-rows=>8,-columns=>26); 619*912701f9SAndroid Build Coastguard Worker print "</TD></TR><TR><TD></TD><TD>"; 620*912701f9SAndroid Build Coastguard Worker print $QUERY->submit(-name=>'Check'); 621*912701f9SAndroid Build Coastguard Worker print "</TD></TR></TABLE>"; 622*912701f9SAndroid Build Coastguard Worker print '<FONT SIZE=-1>Enter a CVS tag and list of bugs to incorporate ' 623*912701f9SAndroid Build Coastguard Worker , 'those bugs into the tag. ' 624*912701f9SAndroid Build Coastguard Worker , 'Specify module(s) above.</FONT>'; 625*912701f9SAndroid Build Coastguard Worker 626*912701f9SAndroid Build Coastguard Worker print "<HR>\n"; 627*912701f9SAndroid Build Coastguard Worker 628*912701f9SAndroid Build Coastguard Worker print $QUERY->submit(-name=>'Reset Insta Cache'), "<BR>"; 629*912701f9SAndroid Build Coastguard Worker print '<FONT SIZE=-1>The insta cache contains the HTML output for previous' 630*912701f9SAndroid Build Coastguard Worker , ' bug diff search results. In some cases (typically during script' 631*912701f9SAndroid Build Coastguard Worker , ' development), it can get out of sync.</FONT>'; 632*912701f9SAndroid Build Coastguard Worker 633*912701f9SAndroid Build Coastguard Worker print "<HR>\n"; 634*912701f9SAndroid Build Coastguard Worker 635*912701f9SAndroid Build Coastguard Worker print $QUERY->submit(-name=>'Delete Cache File:'), " "; 636*912701f9SAndroid Build Coastguard Worker print $QUERY->textfield(-name=>'del_cache',-size=>17), "<BR>"; 637*912701f9SAndroid Build Coastguard Worker print '<FONT SIZE=-1 >Delete a file from the cache. Path is relative' 638*912701f9SAndroid Build Coastguard Worker , ' to cache root and must begin with the module path' 639*912701f9SAndroid Build Coastguard Worker , ' (e.g. "icu/icu").</FONT>'; 640*912701f9SAndroid Build Coastguard Worker 641*912701f9SAndroid Build Coastguard Worker # Propagate params that don't have corresponding form elements 642*912701f9SAndroid Build Coastguard Worker print $QUERY->hidden('user'); 643*912701f9SAndroid Build Coastguard Worker print $QUERY->hidden('debug'); 644*912701f9SAndroid Build Coastguard Worker 645*912701f9SAndroid Build Coastguard Worker print $QUERY->end_form; 646*912701f9SAndroid Build Coastguard Worker} 647*912701f9SAndroid Build Coastguard Worker 648*912701f9SAndroid Build Coastguard Worker# Implement the admin functions. 649*912701f9SAndroid Build Coastguard Workersub emit_adminresult { 650*912701f9SAndroid Build Coastguard Worker print $QUERY->start_html(-title=>$TITLE); 651*912701f9SAndroid Build Coastguard Worker 652*912701f9SAndroid Build Coastguard Worker if ($QUERY->param('Find Bugs')) { 653*912701f9SAndroid Build Coastguard Worker &do_tagscan; 654*912701f9SAndroid Build Coastguard Worker return; 655*912701f9SAndroid Build Coastguard Worker } 656*912701f9SAndroid Build Coastguard Worker 657*912701f9SAndroid Build Coastguard Worker if ($QUERY->param('Check')) { 658*912701f9SAndroid Build Coastguard Worker &do_dcuthelp; 659*912701f9SAndroid Build Coastguard Worker return; 660*912701f9SAndroid Build Coastguard Worker } 661*912701f9SAndroid Build Coastguard Worker 662*912701f9SAndroid Build Coastguard Worker if ($QUERY->param('Reset Insta Cache')) { 663*912701f9SAndroid Build Coastguard Worker resetInstaCache(1); 664*912701f9SAndroid Build Coastguard Worker print "Cache at $INSTA has been erased."; 665*912701f9SAndroid Build Coastguard Worker return; 666*912701f9SAndroid Build Coastguard Worker } 667*912701f9SAndroid Build Coastguard Worker 668*912701f9SAndroid Build Coastguard Worker if ($QUERY->param('Delete Cache File:')) { 669*912701f9SAndroid Build Coastguard Worker my $f = $QUERY->param('del_cache'); 670*912701f9SAndroid Build Coastguard Worker # Careful here -- don't let the user delete anything but a 671*912701f9SAndroid Build Coastguard Worker # legitimate cache file. Watch out for "..", "~", "$", etc. 672*912701f9SAndroid Build Coastguard Worker if ($f !~ m|^[a-z0-9_]+(/[a-z0-9_]+)+\.[a-z0-9]+$|i) { 673*912701f9SAndroid Build Coastguard Worker print "\"$f\" does not look like a valid path."; 674*912701f9SAndroid Build Coastguard Worker return; 675*912701f9SAndroid Build Coastguard Worker } 676*912701f9SAndroid Build Coastguard Worker $f = $CACHE . '/' . $f . ',v'; 677*912701f9SAndroid Build Coastguard Worker if (! -e $f) { 678*912701f9SAndroid Build Coastguard Worker print "\"$f\" does not exist."; 679*912701f9SAndroid Build Coastguard Worker return; 680*912701f9SAndroid Build Coastguard Worker } 681*912701f9SAndroid Build Coastguard Worker if (! -f $f) { 682*912701f9SAndroid Build Coastguard Worker print "\"$f\" is not a file."; 683*912701f9SAndroid Build Coastguard Worker return; 684*912701f9SAndroid Build Coastguard Worker } 685*912701f9SAndroid Build Coastguard Worker unlink($f); 686*912701f9SAndroid Build Coastguard Worker # This check doesn't seem to work. 687*912701f9SAndroid Build Coastguard Worker #if (! -e $f) { 688*912701f9SAndroid Build Coastguard Worker # print "Error: Could not delete \"$f\"."; 689*912701f9SAndroid Build Coastguard Worker # return; 690*912701f9SAndroid Build Coastguard Worker #} else { 691*912701f9SAndroid Build Coastguard Worker print "Cache file \"$f\" deleted."; 692*912701f9SAndroid Build Coastguard Worker #} 693*912701f9SAndroid Build Coastguard Worker return; 694*912701f9SAndroid Build Coastguard Worker } 695*912701f9SAndroid Build Coastguard Worker} 696*912701f9SAndroid Build Coastguard Worker 697*912701f9SAndroid Build Coastguard Worker###################################################################### 698*912701f9SAndroid Build Coastguard Worker# Jitterbug diffs 699*912701f9SAndroid Build Coastguard Worker###################################################################### 700*912701f9SAndroid Build Coastguard Worker 701*912701f9SAndroid Build Coastguard Worker#--------------------------------------------------------------------- 702*912701f9SAndroid Build Coastguard Worker# Find the diffs for a jitterbug and display them. 703*912701f9SAndroid Build Coastguard Worker# Also display other useful links for this bug. 704*912701f9SAndroid Build Coastguard Worker# Param: ID number 705*912701f9SAndroid Build Coastguard Worker# Param: module name ("icu/icu" or "icu4j/icu4j" or other) 706*912701f9SAndroid Build Coastguard Worker# Return: The generated HTML. Also print it to STDOUT 707*912701f9SAndroid Build Coastguard Worker# on the fly. 708*912701f9SAndroid Build Coastguard Workersub generateDiffsList { 709*912701f9SAndroid Build Coastguard Worker my $ID = shift; 710*912701f9SAndroid Build Coastguard Worker my $module = shift; 711*912701f9SAndroid Build Coastguard Worker my $result; 712*912701f9SAndroid Build Coastguard Worker 713*912701f9SAndroid Build Coastguard Worker my $greproot = "$CACHE/$module"; 714*912701f9SAndroid Build Coastguard Worker my $log_url = "$LOG_URL/$module/"; 715*912701f9SAndroid Build Coastguard Worker my $show_url = "$SHOW_URL/$module/"; 716*912701f9SAndroid Build Coastguard Worker my $diff_url = "$DIFF_URL/$module/"; 717*912701f9SAndroid Build Coastguard Worker 718*912701f9SAndroid Build Coastguard Worker # ID matching pattern 719*912701f9SAndroid Build Coastguard Worker my $pat = "0*$ID"; 720*912701f9SAndroid Build Coastguard Worker 721*912701f9SAndroid Build Coastguard Worker # During merging, the bug IDs 1-98 for icu4j were migrated to 722*912701f9SAndroid Build Coastguard Worker # 1301-1398. Therefore, when the user requests a bug in the range 723*912701f9SAndroid Build Coastguard Worker # 1301-1398, we search under both n and n-1300 in icu4j 724*912701f9SAndroid Build Coastguard Worker # repository. 725*912701f9SAndroid Build Coastguard Worker if ($module =~ /^icu4j/ && $ID >= 1301 && $ID <= 1398) { 726*912701f9SAndroid Build Coastguard Worker my $ID2 = $ID - 1300; 727*912701f9SAndroid Build Coastguard Worker $pat = "($pat|0*$ID2)"; 728*912701f9SAndroid Build Coastguard Worker } 729*912701f9SAndroid Build Coastguard Worker 730*912701f9SAndroid Build Coastguard Worker # -E use extended regexp 731*912701f9SAndroid Build Coastguard Worker # -i ignore case 732*912701f9SAndroid Build Coastguard Worker # -I ignore binary files 733*912701f9SAndroid Build Coastguard Worker # -l stop at first match and list file name 734*912701f9SAndroid Build Coastguard Worker # -r recurse 735*912701f9SAndroid Build Coastguard Worker # N/A now that we cache the rlog output 736*912701f9SAndroid Build Coastguard Worker #my $flags = $ignoreBinaries ? "-EiIlr" : "-Eilr"; 737*912701f9SAndroid Build Coastguard Worker 738*912701f9SAndroid Build Coastguard Worker # (1 of 3 REGEXPS) SEE ALSO other regexps; keep them in sync 739*912701f9SAndroid Build Coastguard Worker # TODO improve error handling in following line 740*912701f9SAndroid Build Coastguard Worker my @files = `grep -Eilr "($CVS_MSG_KW)[ \\t]*$pat\\b" $greproot`; 741*912701f9SAndroid Build Coastguard Worker 742*912701f9SAndroid Build Coastguard Worker if (!$QUERY->param('include_attic')) { 743*912701f9SAndroid Build Coastguard Worker @files = grep(!m|/attic/|i, @files); 744*912701f9SAndroid Build Coastguard Worker } 745*912701f9SAndroid Build Coastguard Worker 746*912701f9SAndroid Build Coastguard Worker if (@files < 1) { 747*912701f9SAndroid Build Coastguard Worker $result .= out("No changes found for Jitterbug $ID.\n"); 748*912701f9SAndroid Build Coastguard Worker return $result; 749*912701f9SAndroid Build Coastguard Worker } 750*912701f9SAndroid Build Coastguard Worker 751*912701f9SAndroid Build Coastguard Worker $result .= out("<FONT SIZE=-1>"); 752*912701f9SAndroid Build Coastguard Worker 753*912701f9SAndroid Build Coastguard Worker my $first = 1; 754*912701f9SAndroid Build Coastguard Worker 755*912701f9SAndroid Build Coastguard Worker foreach my $f (sort cmpfiles @files) { 756*912701f9SAndroid Build Coastguard Worker my @r = findRevisions($f, $pat); 757*912701f9SAndroid Build Coastguard Worker 758*912701f9SAndroid Build Coastguard Worker if ($first) { 759*912701f9SAndroid Build Coastguard Worker $first = 0; 760*912701f9SAndroid Build Coastguard Worker } else { 761*912701f9SAndroid Build Coastguard Worker $result .= out("<HR>\n"); 762*912701f9SAndroid Build Coastguard Worker } 763*912701f9SAndroid Build Coastguard Worker 764*912701f9SAndroid Build Coastguard Worker my $localDiff = $QUERY->param('localdiff'); 765*912701f9SAndroid Build Coastguard Worker 766*912701f9SAndroid Build Coastguard Worker my $relFile = $f; 767*912701f9SAndroid Build Coastguard Worker $relFile =~ s/^$greproot\///; 768*912701f9SAndroid Build Coastguard Worker $relFile =~ s/,v//; 769*912701f9SAndroid Build Coastguard Worker my $a = ''; 770*912701f9SAndroid Build Coastguard Worker my $b = $relFile; 771*912701f9SAndroid Build Coastguard Worker if ($b =~ m|(.*/)(.+)|) { 772*912701f9SAndroid Build Coastguard Worker ($a ,$b) = ($1, $2); 773*912701f9SAndroid Build Coastguard Worker } 774*912701f9SAndroid Build Coastguard Worker $result .= out("$a<A href=\"$log_url$relFile?$LOG_URL_SUFFIX\" title=\"View CVS log for $b\"><B>$b</B></A><BR>"); 775*912701f9SAndroid Build Coastguard Worker if (@r > 1) { 776*912701f9SAndroid Build Coastguard Worker # Show diff of earliest to latest. 777*912701f9SAndroid Build Coastguard Worker my $discontiguous = 0; 778*912701f9SAndroid Build Coastguard Worker for (my $i=0; $i<$#r; $i++) { # [sic] from first to last-1 779*912701f9SAndroid Build Coastguard Worker if ($r[$i]->{old} ne $r[$i+1]->{new}) { 780*912701f9SAndroid Build Coastguard Worker $discontiguous = 1; 781*912701f9SAndroid Build Coastguard Worker last; 782*912701f9SAndroid Build Coastguard Worker } 783*912701f9SAndroid Build Coastguard Worker } 784*912701f9SAndroid Build Coastguard Worker my $new = $r[0]->{new}; 785*912701f9SAndroid Build Coastguard Worker my $old = $r[$#r]->{old}; 786*912701f9SAndroid Build Coastguard Worker $result .= out("<CENTER>"); 787*912701f9SAndroid Build Coastguard Worker if ($discontiguous) { 788*912701f9SAndroid Build Coastguard Worker $result .= out("<B>Contains other changes: </B>"); 789*912701f9SAndroid Build Coastguard Worker } 790*912701f9SAndroid Build Coastguard Worker if ($old eq $BASE_REV) { 791*912701f9SAndroid Build Coastguard Worker $result .= out("<A href=\"$show_url$relFile?rev=$new$SHOW_URL_SUFFIX\">"); 792*912701f9SAndroid Build Coastguard Worker $result .= out("<B>View $new</B></A>"); 793*912701f9SAndroid Build Coastguard Worker } else { 794*912701f9SAndroid Build Coastguard Worker $result .= out("<A href=\"$diff_url$relFile?r1=$old&r2=$new$DIFF_URL_SUFFIX\">"); 795*912701f9SAndroid Build Coastguard Worker $result .= out("<B>Diff $new vs $old</B></A>"); 796*912701f9SAndroid Build Coastguard Worker if ($localDiff) { 797*912701f9SAndroid Build Coastguard Worker my $self = $QUERY->url(-full=>1, -query=>1); 798*912701f9SAndroid Build Coastguard Worker my $url = urlPathInfo($self, '/localdiff'); 799*912701f9SAndroid Build Coastguard Worker my $mod = $module; 800*912701f9SAndroid Build Coastguard Worker $mod =~ s|/.+||; 801*912701f9SAndroid Build Coastguard Worker out(" [<A href=\"$url;m=$mod;file=$relFile;r1=$old;r2=$new$DIFF_URL_SUFFIX\">*</A>]"); 802*912701f9SAndroid Build Coastguard Worker } 803*912701f9SAndroid Build Coastguard Worker } 804*912701f9SAndroid Build Coastguard Worker 805*912701f9SAndroid Build Coastguard Worker # Construct contiguous ranges if the overall diff is 806*912701f9SAndroid Build Coastguard Worker # discontiguous. 807*912701f9SAndroid Build Coastguard Worker if ($discontiguous) { 808*912701f9SAndroid Build Coastguard Worker my @ranges; 809*912701f9SAndroid Build Coastguard Worker my $start = 0; 810*912701f9SAndroid Build Coastguard Worker for (my $i=0; $i<$#r; $i++) { # [sic] from first to last-1 811*912701f9SAndroid Build Coastguard Worker if ($r[$i]->{old} ne $r[$i+1]->{new}) { 812*912701f9SAndroid Build Coastguard Worker push @ranges, [$start, $i]; 813*912701f9SAndroid Build Coastguard Worker $start = $i+1; 814*912701f9SAndroid Build Coastguard Worker } 815*912701f9SAndroid Build Coastguard Worker } 816*912701f9SAndroid Build Coastguard Worker push @ranges, [$start, $#r]; 817*912701f9SAndroid Build Coastguard Worker my $first = 1; 818*912701f9SAndroid Build Coastguard Worker foreach my $range (@ranges) { 819*912701f9SAndroid Build Coastguard Worker my $new = $r[$range->[0]]->{new}; 820*912701f9SAndroid Build Coastguard Worker my $old = $r[$range->[1]]->{old}; 821*912701f9SAndroid Build Coastguard Worker if ($first) { 822*912701f9SAndroid Build Coastguard Worker $result .= out("<BR>\n("); 823*912701f9SAndroid Build Coastguard Worker $first = 0; 824*912701f9SAndroid Build Coastguard Worker } else { 825*912701f9SAndroid Build Coastguard Worker $result .= out("<BR>\n"); 826*912701f9SAndroid Build Coastguard Worker } 827*912701f9SAndroid Build Coastguard Worker if ($old eq $BASE_REV) { 828*912701f9SAndroid Build Coastguard Worker $result .= out("<A href=\"$show_url$relFile?rev=$new$SHOW_URL_SUFFIX\">"); 829*912701f9SAndroid Build Coastguard Worker $result .= out("View $new</A>"); 830*912701f9SAndroid Build Coastguard Worker } else { 831*912701f9SAndroid Build Coastguard Worker $result .= out("<A href=\"$diff_url$relFile?r1=$old&r2=$new$DIFF_URL_SUFFIX\">"); 832*912701f9SAndroid Build Coastguard Worker $result .= out("Diff $new vs $old</A>"); 833*912701f9SAndroid Build Coastguard Worker if ($localDiff) { 834*912701f9SAndroid Build Coastguard Worker my $self = $QUERY->url(-full=>1, -query=>1); 835*912701f9SAndroid Build Coastguard Worker my $url = urlPathInfo($self, '/localdiff'); 836*912701f9SAndroid Build Coastguard Worker my $mod = $module; 837*912701f9SAndroid Build Coastguard Worker $mod =~ s|/.+||; 838*912701f9SAndroid Build Coastguard Worker out(" [<A href=\"$url;m=$mod;file=$relFile;r1=$old;r2=$new$DIFF_URL_SUFFIX\">*</A>]"); 839*912701f9SAndroid Build Coastguard Worker } 840*912701f9SAndroid Build Coastguard Worker } 841*912701f9SAndroid Build Coastguard Worker } 842*912701f9SAndroid Build Coastguard Worker $result .= out(")"); 843*912701f9SAndroid Build Coastguard Worker } 844*912701f9SAndroid Build Coastguard Worker 845*912701f9SAndroid Build Coastguard Worker $result .= out("</CENTER>"); 846*912701f9SAndroid Build Coastguard Worker } 847*912701f9SAndroid Build Coastguard Worker 848*912701f9SAndroid Build Coastguard Worker for (my $i=0; $i<@r; $i++) { 849*912701f9SAndroid Build Coastguard Worker my $h = $r[$i]; 850*912701f9SAndroid Build Coastguard Worker my $new = $h->{new}; 851*912701f9SAndroid Build Coastguard Worker my $old = $h->{old}; 852*912701f9SAndroid Build Coastguard Worker if ($old eq $BASE_REV) { 853*912701f9SAndroid Build Coastguard Worker $result .= out("<A href=\"$show_url$relFile?rev=$new$SHOW_URL_SUFFIX\">"); 854*912701f9SAndroid Build Coastguard Worker $result .= out("<B>View $new</B></A>"); 855*912701f9SAndroid Build Coastguard Worker } else { 856*912701f9SAndroid Build Coastguard Worker $result .= out("<A href=\"$diff_url$relFile?r1=$old&r2=$new$DIFF_URL_SUFFIX\">"); 857*912701f9SAndroid Build Coastguard Worker $result .= out("<B>Diff $new</B></A>"); 858*912701f9SAndroid Build Coastguard Worker if ($localDiff) { 859*912701f9SAndroid Build Coastguard Worker my $self = $QUERY->url(-full=>1, -query=>1); 860*912701f9SAndroid Build Coastguard Worker my $url = urlPathInfo($self, '/localdiff'); 861*912701f9SAndroid Build Coastguard Worker my $mod = $module; 862*912701f9SAndroid Build Coastguard Worker $mod =~ s|/.+||; 863*912701f9SAndroid Build Coastguard Worker out(" [<A href=\"$url;m=$mod;file=$relFile;r1=$old;r2=$new$DIFF_URL_SUFFIX\">*</A>]"); 864*912701f9SAndroid Build Coastguard Worker } 865*912701f9SAndroid Build Coastguard Worker } 866*912701f9SAndroid Build Coastguard Worker $result .= out(" <EM>", $h->{date}, "</EM> by <EM>", $h->{author}, "</EM><BR>"); 867*912701f9SAndroid Build Coastguard Worker $result .= out($h->{comment}); 868*912701f9SAndroid Build Coastguard Worker $result .= out("<BR>\n"); 869*912701f9SAndroid Build Coastguard Worker } 870*912701f9SAndroid Build Coastguard Worker } 871*912701f9SAndroid Build Coastguard Worker 872*912701f9SAndroid Build Coastguard Worker $result .= out("</FONT>"); 873*912701f9SAndroid Build Coastguard Worker $result; 874*912701f9SAndroid Build Coastguard Worker} 875*912701f9SAndroid Build Coastguard Worker 876*912701f9SAndroid Build Coastguard Worker# Sort criterion for file diffs 877*912701f9SAndroid Build Coastguard Workersub cmpfiles { 878*912701f9SAndroid Build Coastguard Worker my $aa = $a; 879*912701f9SAndroid Build Coastguard Worker my $bb = $b; 880*912701f9SAndroid Build Coastguard Worker $aa =~ s|/unicode(/[^/]+)$|$1|; 881*912701f9SAndroid Build Coastguard Worker $bb =~ s|/unicode(/[^/]+)$|$1|; 882*912701f9SAndroid Build Coastguard Worker $aa =~ s|\.h,|.1h,|; 883*912701f9SAndroid Build Coastguard Worker $bb =~ s|\.h,|.1h,|; 884*912701f9SAndroid Build Coastguard Worker return $aa cmp $bb; 885*912701f9SAndroid Build Coastguard Worker} 886*912701f9SAndroid Build Coastguard Worker 887*912701f9SAndroid Build Coastguard Worker# Sort criterion for revision numbers, e.g. "1.9" vs "1.10" 888*912701f9SAndroid Build Coastguard Workersub cmprevs { 889*912701f9SAndroid Build Coastguard Worker my @a = split('\.', $a); 890*912701f9SAndroid Build Coastguard Worker my @b = split('\.', $b); 891*912701f9SAndroid Build Coastguard Worker for (my $i=0; $i<=$#a && $i<=$#b; ++$i) { 892*912701f9SAndroid Build Coastguard Worker my $c = $b[$i] - $a[$i]; 893*912701f9SAndroid Build Coastguard Worker return $c if ($c); 894*912701f9SAndroid Build Coastguard Worker } 895*912701f9SAndroid Build Coastguard Worker return $#b - $#a; 896*912701f9SAndroid Build Coastguard Worker} 897*912701f9SAndroid Build Coastguard Worker 898*912701f9SAndroid Build Coastguard Worker###################################################################### 899*912701f9SAndroid Build Coastguard Worker# tagscan 900*912701f9SAndroid Build Coastguard Worker###################################################################### 901*912701f9SAndroid Build Coastguard Worker 902*912701f9SAndroid Build Coastguard Worker# Perform a "tagscan" and emit the results. A tagscan is a scan of 903*912701f9SAndroid Build Coastguard Worker# the CVS rlog cache in which bug IDs between two tags are compiled. 904*912701f9SAndroid Build Coastguard Worker# If a file is marked 'dead' it is ignored. If it was created after 905*912701f9SAndroid Build Coastguard Worker# the latest date of the HI tag (as determined by checking _every_ 906*912701f9SAndroid Build Coastguard Worker# file's date for that tag) then it is ignored. 907*912701f9SAndroid Build Coastguard Workersub do_tagscan { 908*912701f9SAndroid Build Coastguard Worker $TAGSCAN_TAG_LO = expandTag($QUERY->param('tag_lo')); 909*912701f9SAndroid Build Coastguard Worker $TAGSCAN_TAG_HI = expandTag($QUERY->param('tag_hi')); 910*912701f9SAndroid Build Coastguard Worker 911*912701f9SAndroid Build Coastguard Worker $TAGSCAN_TAG_HI_DATE = ''; 912*912701f9SAndroid Build Coastguard Worker 913*912701f9SAndroid Build Coastguard Worker if (!$TAGSCAN_TAG_LO || !$TAGSCAN_TAG_HI) { 914*912701f9SAndroid Build Coastguard Worker print "Please enter two CVS tags and try again."; 915*912701f9SAndroid Build Coastguard Worker return; 916*912701f9SAndroid Build Coastguard Worker } 917*912701f9SAndroid Build Coastguard Worker 918*912701f9SAndroid Build Coastguard Worker my $user = $QUERY->param('user'); 919*912701f9SAndroid Build Coastguard Worker 920*912701f9SAndroid Build Coastguard Worker my @m; 921*912701f9SAndroid Build Coastguard Worker return if (!parseMod(\@m)); # what modules are we searching? 922*912701f9SAndroid Build Coastguard Worker 923*912701f9SAndroid Build Coastguard Worker # Slight limitation -- our tagLink will only refer to the first module 924*912701f9SAndroid Build Coastguard Worker print "Searching module(s) <B>", join(", ", @m) 925*912701f9SAndroid Build Coastguard Worker , "</B> for bugs after tag <B>", 926*912701f9SAndroid Build Coastguard Worker tagLink($TAGSCAN_TAG_LO,$m[0],'grepj_2'), 927*912701f9SAndroid Build Coastguard Worker "</B> up to and including tag <B>", 928*912701f9SAndroid Build Coastguard Worker tagLink($TAGSCAN_TAG_HI,$m[0],'grepj_2'), 929*912701f9SAndroid Build Coastguard Worker "</B>. <EM>Note: Dead files and Attic files will be ignored.</EM><BR>\n"; 930*912701f9SAndroid Build Coastguard Worker 931*912701f9SAndroid Build Coastguard Worker foreach (@m) { 932*912701f9SAndroid Build Coastguard Worker updateCacheDir($_); 933*912701f9SAndroid Build Coastguard Worker } 934*912701f9SAndroid Build Coastguard Worker 935*912701f9SAndroid Build Coastguard Worker if ($UPDATE_COUNT) { 936*912701f9SAndroid Build Coastguard Worker print "done ($UPDATE_NONATTIC_COUNT,$UPDATE_ATTIC_COUNT)."; 937*912701f9SAndroid Build Coastguard Worker } 938*912701f9SAndroid Build Coastguard Worker 939*912701f9SAndroid Build Coastguard Worker %TAGSCAN_IDS = (); 940*912701f9SAndroid Build Coastguard Worker#at %TAGSCAN_ALLTAGS = (); 941*912701f9SAndroid Build Coastguard Worker %TAGSCAN_WHY = (); 942*912701f9SAndroid Build Coastguard Worker $TAGSCAN_COUNT = 0; 943*912701f9SAndroid Build Coastguard Worker print "<HR>Scanning CVS tree for bug IDs..."; 944*912701f9SAndroid Build Coastguard Worker foreach (@m) { 945*912701f9SAndroid Build Coastguard Worker tagscanDir($_); 946*912701f9SAndroid Build Coastguard Worker } 947*912701f9SAndroid Build Coastguard Worker print "done.<HR>"; 948*912701f9SAndroid Build Coastguard Worker 949*912701f9SAndroid Build Coastguard Worker # Filter out tagless files that were created after the HI tag 950*912701f9SAndroid Build Coastguard Worker # date. 951*912701f9SAndroid Build Coastguard Worker my @a; 952*912701f9SAndroid Build Coastguard Worker foreach my $f (@TAGLESS_FILES) { 953*912701f9SAndroid Build Coastguard Worker my $d = getRev11Date("$CACHE/$f"); 954*912701f9SAndroid Build Coastguard Worker if ($d && $d le $TAGSCAN_TAG_HI_DATE) { 955*912701f9SAndroid Build Coastguard Worker push @a, $f; 956*912701f9SAndroid Build Coastguard Worker } 957*912701f9SAndroid Build Coastguard Worker } 958*912701f9SAndroid Build Coastguard Worker @TAGLESS_FILES = @a; 959*912701f9SAndroid Build Coastguard Worker 960*912701f9SAndroid Build Coastguard Worker if (@NO_JITTERBUG_FILES) { 961*912701f9SAndroid Build Coastguard Worker print "The following revisions have no associated Jitterbug, or the bug number could not be parsed from the checkin comment.\n"; 962*912701f9SAndroid Build Coastguard Worker print "Checkins older than a year are not listed.\n"; 963*912701f9SAndroid Build Coastguard Worker print "<BLOCKQUOTE>"; 964*912701f9SAndroid Build Coastguard Worker print join("<BR>\n", 965*912701f9SAndroid Build Coastguard Worker map {logLink($_->[0],'grepj_2') . 966*912701f9SAndroid Build Coastguard Worker ", " . $_->[1] . "<BR><CODE>" . 967*912701f9SAndroid Build Coastguard Worker $_->[2] . "</CODE>"} 968*912701f9SAndroid Build Coastguard Worker @NO_JITTERBUG_FILES); 969*912701f9SAndroid Build Coastguard Worker print "</BLOCKQUOTE><HR>\n"; 970*912701f9SAndroid Build Coastguard Worker } 971*912701f9SAndroid Build Coastguard Worker 972*912701f9SAndroid Build Coastguard Worker if (@TAGLESS_FILES) { 973*912701f9SAndroid Build Coastguard Worker print "<EM>The following ", scalar @TAGLESS_FILES 974*912701f9SAndroid Build Coastguard Worker , " files were ignored because they are missing one or both tags." 975*912701f9SAndroid Build Coastguard Worker , " </EM>Files created after <B>$TAGSCAN_TAG_HI</B> should not be listed" 976*912701f9SAndroid Build Coastguard Worker , " here.\n<BLOCKQUOTE>"; 977*912701f9SAndroid Build Coastguard Worker print join("<BR>\n", 978*912701f9SAndroid Build Coastguard Worker map {logLink($_,'grepj_2')} 979*912701f9SAndroid Build Coastguard Worker @TAGLESS_FILES) 980*912701f9SAndroid Build Coastguard Worker , "</BLOCKQUOTE><HR>\n"; 981*912701f9SAndroid Build Coastguard Worker } 982*912701f9SAndroid Build Coastguard Worker 983*912701f9SAndroid Build Coastguard Worker if (@BRANCHED_FILES) { 984*912701f9SAndroid Build Coastguard Worker print "<EM>The following ", scalar @BRANCHED_FILES 985*912701f9SAndroid Build Coastguard Worker , " files were ignored because the tags occur on different" 986*912701f9SAndroid Build Coastguard Worker , " branches.\n</EM><BLOCKQUOTE>"; 987*912701f9SAndroid Build Coastguard Worker print join("<BR>\n", 988*912701f9SAndroid Build Coastguard Worker map {logLink($_->[0],'grepj_2') . 989*912701f9SAndroid Build Coastguard Worker ": " . $_->[1] . " => " . $_->[2]} 990*912701f9SAndroid Build Coastguard Worker @BRANCHED_FILES) 991*912701f9SAndroid Build Coastguard Worker , "</BLOCKQUOTE><HR>\n"; 992*912701f9SAndroid Build Coastguard Worker } 993*912701f9SAndroid Build Coastguard Worker 994*912701f9SAndroid Build Coastguard Worker#at print "Other tags seen: ", 995*912701f9SAndroid Build Coastguard Worker#at join(" ", 996*912701f9SAndroid Build Coastguard Worker#at map {my $a=tagToRelease($_); $a?"$_($a)":"$_*"} 997*912701f9SAndroid Build Coastguard Worker#at sort keys %TAGSCAN_ALLTAGS), "\n<HR>"; 998*912701f9SAndroid Build Coastguard Worker 999*912701f9SAndroid Build Coastguard Worker print "Details: " 1000*912701f9SAndroid Build Coastguard Worker , join("; ", 1001*912701f9SAndroid Build Coastguard Worker map {"(" . jitterbugLink($user, $_, 'grepj_2') . 1002*912701f9SAndroid Build Coastguard Worker ": " . join(", ", 1003*912701f9SAndroid Build Coastguard Worker map {s|^.+?/||; s|,v$||; $_} sort keys %{$TAGSCAN_WHY{$_}}) . ")"} 1004*912701f9SAndroid Build Coastguard Worker sort {$a<=>$b} keys %TAGSCAN_WHY) 1005*912701f9SAndroid Build Coastguard Worker , "<HR>\n"; 1006*912701f9SAndroid Build Coastguard Worker 1007*912701f9SAndroid Build Coastguard Worker print "Jitterbug IDs found (",scalar keys %TAGSCAN_IDS,"): " 1008*912701f9SAndroid Build Coastguard Worker , join(", ", 1009*912701f9SAndroid Build Coastguard Worker map {jitterbugLink($user, $_, 'grepj_2')} 1010*912701f9SAndroid Build Coastguard Worker sort {$a<=>$b} keys %TAGSCAN_IDS); 1011*912701f9SAndroid Build Coastguard Worker 1012*912701f9SAndroid Build Coastguard Worker my $bugs = join(',', sort {$a<=>$b} keys %TAGSCAN_IDS); 1013*912701f9SAndroid Build Coastguard Worker print <<END; 1014*912701f9SAndroid Build Coastguard Worker <form method=post action=http://bugs.icu-project.org/cgibin/private/tasklist/buglist.html> 1015*912701f9SAndroid Build Coastguard Worker <input type=hidden name=tag1 value=$TAGSCAN_TAG_LO> 1016*912701f9SAndroid Build Coastguard Worker <input type=hidden name=tag2 value=$TAGSCAN_TAG_HI> 1017*912701f9SAndroid Build Coastguard Worker <input type=hidden name=bugs value="$bugs"> 1018*912701f9SAndroid Build Coastguard Worker <input type=submit value="Bug List Report"> 1019*912701f9SAndroid Build Coastguard Worker </form> 1020*912701f9SAndroid Build Coastguard WorkerEND 1021*912701f9SAndroid Build Coastguard Worker my $bugs2 = join(' ', sort {$a<=>$b} keys %TAGSCAN_IDS); 1022*912701f9SAndroid Build Coastguard Worker print <<END; 1023*912701f9SAndroid Build Coastguard Worker <form method=GET action=http://bugs.icu-project.org/cgibin/private/byname/review> 1024*912701f9SAndroid Build Coastguard Worker <input type=hidden name=user value=$user> 1025*912701f9SAndroid Build Coastguard Worker <input type=hidden name=bugs value="$bugs2"> 1026*912701f9SAndroid Build Coastguard Worker <input type=hidden name=showclosed value=> 1027*912701f9SAndroid Build Coastguard Worker <input type=submit value="Reviewer Report"> 1028*912701f9SAndroid Build Coastguard Worker </form> 1029*912701f9SAndroid Build Coastguard WorkerEND 1030*912701f9SAndroid Build Coastguard Worker print <<END; 1031*912701f9SAndroid Build Coastguard Worker <form method=GET action=http://bugs.icu-project.org/cgibin/private/byname/assign> 1032*912701f9SAndroid Build Coastguard Worker <input type=hidden name=user value=$user> 1033*912701f9SAndroid Build Coastguard Worker <input type=hidden name=bugs value="$bugs2"> 1034*912701f9SAndroid Build Coastguard Worker <input type=hidden name=showclosed value=> 1035*912701f9SAndroid Build Coastguard Worker <input type=submit value="Assignee Report"> 1036*912701f9SAndroid Build Coastguard Worker </form> 1037*912701f9SAndroid Build Coastguard WorkerEND 1038*912701f9SAndroid Build Coastguard Worker} 1039*912701f9SAndroid Build Coastguard Worker 1040*912701f9SAndroid Build Coastguard Worker# Given a relative path to $CVSROOT, tagscan the 1041*912701f9SAndroid Build Coastguard Worker# corresponding item under $CACHE. Path may point to a 1042*912701f9SAndroid Build Coastguard Worker# file or a directory. 1043*912701f9SAndroid Build Coastguard Worker# @param relative directory, not ending in "/", e.g. "icu/icu" 1044*912701f9SAndroid Build Coastguard Worker# @param item name in that directory 1045*912701f9SAndroid Build Coastguard Workersub tagscanEntry { 1046*912701f9SAndroid Build Coastguard Worker my $relDir = shift; 1047*912701f9SAndroid Build Coastguard Worker my $item = shift; # A file or dir in $CVSROOT/$relDir 1048*912701f9SAndroid Build Coastguard Worker 1049*912701f9SAndroid Build Coastguard Worker if (-d "$CACHE/$relDir/$item") { 1050*912701f9SAndroid Build Coastguard Worker tagscanDir("$relDir/$item"); 1051*912701f9SAndroid Build Coastguard Worker } elsif ($item =~ /,v$/) { 1052*912701f9SAndroid Build Coastguard Worker tagscanFile("$relDir/$item"); 1053*912701f9SAndroid Build Coastguard Worker } 1054*912701f9SAndroid Build Coastguard Worker} 1055*912701f9SAndroid Build Coastguard Worker 1056*912701f9SAndroid Build Coastguard Worker# Given a relative directory path to $CACHE, tagscan the 1057*912701f9SAndroid Build Coastguard Worker# underlying files. 1058*912701f9SAndroid Build Coastguard Worker# @param relative directory, not ending in "/", e.g. "icu/icu" 1059*912701f9SAndroid Build Coastguard Workersub tagscanDir { 1060*912701f9SAndroid Build Coastguard Worker my $relDir = shift; 1061*912701f9SAndroid Build Coastguard Worker 1062*912701f9SAndroid Build Coastguard Worker # Ignore stuff in the Attic 1063*912701f9SAndroid Build Coastguard Worker return if ($relDir eq 'Attic'); 1064*912701f9SAndroid Build Coastguard Worker 1065*912701f9SAndroid Build Coastguard Worker debugOut("+tagscanDir($relDir)") if ($DEBUG); 1066*912701f9SAndroid Build Coastguard Worker 1067*912701f9SAndroid Build Coastguard Worker my $cacheDir = "$CACHE/$relDir"; 1068*912701f9SAndroid Build Coastguard Worker 1069*912701f9SAndroid Build Coastguard Worker # First tagscan files in this directory 1070*912701f9SAndroid Build Coastguard Worker opendir(DIR, $cacheDir); 1071*912701f9SAndroid Build Coastguard Worker my @cacheList = grep !/^\.\.?$/, readdir(DIR); 1072*912701f9SAndroid Build Coastguard Worker closedir(DIR); 1073*912701f9SAndroid Build Coastguard Worker 1074*912701f9SAndroid Build Coastguard Worker # Tagscan each individual entry 1075*912701f9SAndroid Build Coastguard Worker foreach (@cacheList) { 1076*912701f9SAndroid Build Coastguard Worker tagscanEntry($relDir, $_); 1077*912701f9SAndroid Build Coastguard Worker } 1078*912701f9SAndroid Build Coastguard Worker 1079*912701f9SAndroid Build Coastguard Worker debugOut("-tagscanDir($relDir)") if ($DEBUG); 1080*912701f9SAndroid Build Coastguard Worker} 1081*912701f9SAndroid Build Coastguard Worker 1082*912701f9SAndroid Build Coastguard Worker# Given a relative file path to $CVSROOT, tagscan the 1083*912701f9SAndroid Build Coastguard Worker# corresponding file under $CACHE, if necessary. 1084*912701f9SAndroid Build Coastguard Worker# @param relative file path 1085*912701f9SAndroid Build Coastguard Workersub tagscanFile { 1086*912701f9SAndroid Build Coastguard Worker my $relFile = shift; 1087*912701f9SAndroid Build Coastguard Worker 1088*912701f9SAndroid Build Coastguard Worker # Display progress; it takes awhile 1089*912701f9SAndroid Build Coastguard Worker if (++$TAGSCAN_COUNT % 100 == 0) { 1090*912701f9SAndroid Build Coastguard Worker print " $TAGSCAN_COUNT..."; 1091*912701f9SAndroid Build Coastguard Worker } 1092*912701f9SAndroid Build Coastguard Worker 1093*912701f9SAndroid Build Coastguard Worker # This file contains the output of rlog. 1094*912701f9SAndroid Build Coastguard Worker my $file = "$CACHE/$relFile"; 1095*912701f9SAndroid Build Coastguard Worker 1096*912701f9SAndroid Build Coastguard Worker # Parse the rlog file. Start by extracting the tag names. Look 1097*912701f9SAndroid Build Coastguard Worker # for the TAGSCAN_TAG_LO and TAGSCAN_TAG_HI's associated revision 1098*912701f9SAndroid Build Coastguard Worker # numbers. 1099*912701f9SAndroid Build Coastguard Worker open(IN, $file); 1100*912701f9SAndroid Build Coastguard Worker while (<IN>) { 1101*912701f9SAndroid Build Coastguard Worker last if (/^symbolic names:\s*$/); 1102*912701f9SAndroid Build Coastguard Worker } 1103*912701f9SAndroid Build Coastguard Worker my $rev_lo; 1104*912701f9SAndroid Build Coastguard Worker my $rev_hi; 1105*912701f9SAndroid Build Coastguard Worker my $rel_min; # lowest release number seen 1106*912701f9SAndroid Build Coastguard Worker my @odd_tags; 1107*912701f9SAndroid Build Coastguard Worker if ($TAGSCAN_TAG_HI eq 'HEAD') { 1108*912701f9SAndroid Build Coastguard Worker $rev_hi = 'HEAD'; 1109*912701f9SAndroid Build Coastguard Worker } 1110*912701f9SAndroid Build Coastguard Worker while (<IN>) { 1111*912701f9SAndroid Build Coastguard Worker last if (/^\S/); 1112*912701f9SAndroid Build Coastguard Worker if (!$rev_lo && /^\s+$TAGSCAN_TAG_LO:\s*(\S+)/) { 1113*912701f9SAndroid Build Coastguard Worker $rev_lo = $1; 1114*912701f9SAndroid Build Coastguard Worker } 1115*912701f9SAndroid Build Coastguard Worker elsif (!$rev_hi && /^\s+$TAGSCAN_TAG_HI:\s*(\S+)/) { 1116*912701f9SAndroid Build Coastguard Worker $rev_hi = $1; 1117*912701f9SAndroid Build Coastguard Worker } 1118*912701f9SAndroid Build Coastguard Worker elsif (/^\s+(\S+?):/) { 1119*912701f9SAndroid Build Coastguard Worker my $tag = $1; 1120*912701f9SAndroid Build Coastguard Worker#at $TAGSCAN_ALLTAGS{$tag} = 1; 1121*912701f9SAndroid Build Coastguard Worker my $r = tagToRelease($tag); 1122*912701f9SAndroid Build Coastguard Worker if ($r) { 1123*912701f9SAndroid Build Coastguard Worker if (!$rel_min) { 1124*912701f9SAndroid Build Coastguard Worker $rel_min = $r; 1125*912701f9SAndroid Build Coastguard Worker } elsif ($r < $rel_min) { 1126*912701f9SAndroid Build Coastguard Worker $rel_min = $r; 1127*912701f9SAndroid Build Coastguard Worker } 1128*912701f9SAndroid Build Coastguard Worker } else { 1129*912701f9SAndroid Build Coastguard Worker push @odd_tags, $tag; 1130*912701f9SAndroid Build Coastguard Worker } 1131*912701f9SAndroid Build Coastguard Worker } 1132*912701f9SAndroid Build Coastguard Worker } 1133*912701f9SAndroid Build Coastguard Worker 1134*912701f9SAndroid Build Coastguard Worker # Check for dead files. Look ahead and find the state of the head 1135*912701f9SAndroid Build Coastguard Worker # revision. 1136*912701f9SAndroid Build Coastguard Worker my $pos = tell(IN); 1137*912701f9SAndroid Build Coastguard Worker my $state = ''; 1138*912701f9SAndroid Build Coastguard Worker while (<IN>) { 1139*912701f9SAndroid Build Coastguard Worker if (/^date:.+state: ([A-Za-z]+)/) { 1140*912701f9SAndroid Build Coastguard Worker $state = $1; 1141*912701f9SAndroid Build Coastguard Worker last; 1142*912701f9SAndroid Build Coastguard Worker } 1143*912701f9SAndroid Build Coastguard Worker } 1144*912701f9SAndroid Build Coastguard Worker seek(IN,$pos,0); 1145*912701f9SAndroid Build Coastguard Worker 1146*912701f9SAndroid Build Coastguard Worker # If this file is 'dead', we're done. 1147*912701f9SAndroid Build Coastguard Worker return if ($state eq 'dead'); 1148*912701f9SAndroid Build Coastguard Worker 1149*912701f9SAndroid Build Coastguard Worker # Usually we find both tags. However, in several special cases one 1150*912701f9SAndroid Build Coastguard Worker # or both tags will be missing. 1151*912701f9SAndroid Build Coastguard Worker if (!$rev_lo || !$rev_hi) { 1152*912701f9SAndroid Build Coastguard Worker my $ok = 0; 1153*912701f9SAndroid Build Coastguard Worker 1154*912701f9SAndroid Build Coastguard Worker # If we see the high tag, but not the low, then this may be a 1155*912701f9SAndroid Build Coastguard Worker # new file (created after the low tag). To check for this, examine 1156*912701f9SAndroid Build Coastguard Worker # the other tags. If this is a new file; we can just scan 1157*912701f9SAndroid Build Coastguard Worker # from rev_hi all the end of the log (with rev_lo set to '1.1'). 1158*912701f9SAndroid Build Coastguard Worker if ($rev_hi) { 1159*912701f9SAndroid Build Coastguard Worker if (!$rel_min) { 1160*912701f9SAndroid Build Coastguard Worker # The only tag seen was the HI tag. 1161*912701f9SAndroid Build Coastguard Worker $ok = 1; 1162*912701f9SAndroid Build Coastguard Worker } else { 1163*912701f9SAndroid Build Coastguard Worker my $lo = tagToRelease($TAGSCAN_TAG_LO); 1164*912701f9SAndroid Build Coastguard Worker if ($lo && $rel_min > $lo && (scalar @odd_tags)==0) { 1165*912701f9SAndroid Build Coastguard Worker # Other tags were seen, but all were above the LO tag. 1166*912701f9SAndroid Build Coastguard Worker $ok = 1; 1167*912701f9SAndroid Build Coastguard Worker } 1168*912701f9SAndroid Build Coastguard Worker } 1169*912701f9SAndroid Build Coastguard Worker $rev_lo = '1.1'; 1170*912701f9SAndroid Build Coastguard Worker } 1171*912701f9SAndroid Build Coastguard Worker 1172*912701f9SAndroid Build Coastguard Worker if (!$ok) { 1173*912701f9SAndroid Build Coastguard Worker push @TAGLESS_FILES, $relFile; 1174*912701f9SAndroid Build Coastguard Worker return; 1175*912701f9SAndroid Build Coastguard Worker } 1176*912701f9SAndroid Build Coastguard Worker } 1177*912701f9SAndroid Build Coastguard Worker 1178*912701f9SAndroid Build Coastguard Worker # If the low and high revisions are the same then there are no bugs 1179*912701f9SAndroid Build Coastguard Worker # to record from this file. 1180*912701f9SAndroid Build Coastguard Worker if ($rev_lo eq $rev_hi) { 1181*912701f9SAndroid Build Coastguard Worker # Scan down to get the date of the rev_hi 1182*912701f9SAndroid Build Coastguard Worker while (<IN>) { 1183*912701f9SAndroid Build Coastguard Worker if (/^revision $rev_hi\s*$/) { 1184*912701f9SAndroid Build Coastguard Worker $_ = <IN>; # Read date line 1185*912701f9SAndroid Build Coastguard Worker if (/^date: (.+?);/) { 1186*912701f9SAndroid Build Coastguard Worker $TAGSCAN_TAG_HI_DATE = $1 1187*912701f9SAndroid Build Coastguard Worker if ($TAGSCAN_TAG_HI_DATE lt $1); 1188*912701f9SAndroid Build Coastguard Worker } else { 1189*912701f9SAndroid Build Coastguard Worker cantParse('date', $relFile, $_, $rev_hi); 1190*912701f9SAndroid Build Coastguard Worker } 1191*912701f9SAndroid Build Coastguard Worker } 1192*912701f9SAndroid Build Coastguard Worker } 1193*912701f9SAndroid Build Coastguard Worker return; 1194*912701f9SAndroid Build Coastguard Worker } 1195*912701f9SAndroid Build Coastguard Worker 1196*912701f9SAndroid Build Coastguard Worker my $inRange; 1197*912701f9SAndroid Build Coastguard Worker 1198*912701f9SAndroid Build Coastguard Worker my @result; 1199*912701f9SAndroid Build Coastguard Worker 1200*912701f9SAndroid Build Coastguard Worker # The rlog output (the CACHE file) contains a series 1201*912701f9SAndroid Build Coastguard Worker # of groups of lines, like so: 1202*912701f9SAndroid Build Coastguard Worker #|---------------------------- 1203*912701f9SAndroid Build Coastguard Worker #|revision 1.40 1204*912701f9SAndroid Build Coastguard Worker #|date: 2001/08/02 18:24:58; author: grhoten; state: Exp; lines: +82 -73 1205*912701f9SAndroid Build Coastguard Worker #|jitterbug 1080: general readme.html updates 1206*912701f9SAndroid Build Coastguard Worker # That is, the first line has the revision #. 1207*912701f9SAndroid Build Coastguard Worker # The third line has the bug ID. 1208*912701f9SAndroid Build Coastguard Worker 1209*912701f9SAndroid Build Coastguard Worker # Are revisions on the same branch? 1210*912701f9SAndroid Build Coastguard Worker my $branch_lo = revToBranch($rev_lo); 1211*912701f9SAndroid Build Coastguard Worker my $branch_hi = revToBranch($rev_hi); 1212*912701f9SAndroid Build Coastguard Worker if ($branch_lo eq $branch_hi) { 1213*912701f9SAndroid Build Coastguard Worker 1214*912701f9SAndroid Build Coastguard Worker while (<IN>) { 1215*912701f9SAndroid Build Coastguard Worker if (/^-{20,}$/) { 1216*912701f9SAndroid Build Coastguard Worker $_ = <IN>; # Read revision line 1217*912701f9SAndroid Build Coastguard Worker if (/revision (\S+)/) { 1218*912701f9SAndroid Build Coastguard Worker my $rev = $1; 1219*912701f9SAndroid Build Coastguard Worker last if ($rev eq $rev_lo); 1220*912701f9SAndroid Build Coastguard Worker if (!$inRange) { 1221*912701f9SAndroid Build Coastguard Worker if ($rev eq $rev_hi || $rev_hi eq 'HEAD') { 1222*912701f9SAndroid Build Coastguard Worker $inRange = 1; 1223*912701f9SAndroid Build Coastguard Worker } 1224*912701f9SAndroid Build Coastguard Worker } 1225*912701f9SAndroid Build Coastguard Worker if ($inRange) { 1226*912701f9SAndroid Build Coastguard Worker my $date = <IN>; # Read date line 1227*912701f9SAndroid Build Coastguard Worker $_ = <IN>; # Read comment or branches: line 1228*912701f9SAndroid Build Coastguard Worker $_ = <IN> if (/^branches:/); # Read line after branches: 1229*912701f9SAndroid Build Coastguard Worker my $id; 1230*912701f9SAndroid Build Coastguard Worker if (/^\s*jitterbug\s+0*(\d+)/i) { 1231*912701f9SAndroid Build Coastguard Worker $id = $1; 1232*912701f9SAndroid Build Coastguard Worker } else { 1233*912701f9SAndroid Build Coastguard Worker push @NO_JITTERBUG_FILES, [$relFile, $rev, $_] 1234*912701f9SAndroid Build Coastguard Worker if (noJitterbugFilter($rev, $date)); 1235*912701f9SAndroid Build Coastguard Worker $id = $NO_JITTERBUG; 1236*912701f9SAndroid Build Coastguard Worker } 1237*912701f9SAndroid Build Coastguard Worker push @result, [$rev, $id, $date]; 1238*912701f9SAndroid Build Coastguard Worker } 1239*912701f9SAndroid Build Coastguard Worker } else { 1240*912701f9SAndroid Build Coastguard Worker cantParse('revision', $relFile, $_); 1241*912701f9SAndroid Build Coastguard Worker last; # This is very bad - bail out 1242*912701f9SAndroid Build Coastguard Worker } 1243*912701f9SAndroid Build Coastguard Worker } 1244*912701f9SAndroid Build Coastguard Worker } 1245*912701f9SAndroid Build Coastguard Worker } 1246*912701f9SAndroid Build Coastguard Worker 1247*912701f9SAndroid Build Coastguard Worker elsif ($branch_hi =~ /^\Q$branch_lo\E\./) { 1248*912701f9SAndroid Build Coastguard Worker # Special case: E.g., going from 1.25 => 1.25.2.1 means 1249*912701f9SAndroid Build Coastguard Worker # going from branch 1 to 1.25.2. We can handle this. 1250*912701f9SAndroid Build Coastguard Worker 1251*912701f9SAndroid Build Coastguard Worker my @revs = traverseRevisions($rev_lo, $rev_hi); 1252*912701f9SAndroid Build Coastguard Worker 1253*912701f9SAndroid Build Coastguard Worker #print "[$relFile: ", join(",",@revs), "]"; 1254*912701f9SAndroid Build Coastguard Worker 1255*912701f9SAndroid Build Coastguard Worker shift(@revs); # discard rev_lo 1256*912701f9SAndroid Build Coastguard Worker my %revs; 1257*912701f9SAndroid Build Coastguard Worker foreach (@revs) { $revs{$_} = 1; } # convert to hash 1258*912701f9SAndroid Build Coastguard Worker 1259*912701f9SAndroid Build Coastguard Worker while (<IN>) { 1260*912701f9SAndroid Build Coastguard Worker if (/^-{20,}$/) { 1261*912701f9SAndroid Build Coastguard Worker $_ = <IN>; # Read revision line 1262*912701f9SAndroid Build Coastguard Worker if (/revision (\S+)/) { 1263*912701f9SAndroid Build Coastguard Worker my $rev = $1; 1264*912701f9SAndroid Build Coastguard Worker if (exists $revs{$rev}) { 1265*912701f9SAndroid Build Coastguard Worker delete $revs{$rev}; 1266*912701f9SAndroid Build Coastguard Worker my $date = <IN>; # Read date line 1267*912701f9SAndroid Build Coastguard Worker if ($rev eq $rev_hi) { 1268*912701f9SAndroid Build Coastguard Worker # Record latest date corresponding to HI tag 1269*912701f9SAndroid Build Coastguard Worker if ($date =~ /^date: (.+?);/) { 1270*912701f9SAndroid Build Coastguard Worker $TAGSCAN_TAG_HI_DATE = $1 1271*912701f9SAndroid Build Coastguard Worker if ($TAGSCAN_TAG_HI_DATE lt $1); 1272*912701f9SAndroid Build Coastguard Worker } else { 1273*912701f9SAndroid Build Coastguard Worker cantParse('date', $relFile, $date, $rev); 1274*912701f9SAndroid Build Coastguard Worker } 1275*912701f9SAndroid Build Coastguard Worker } 1276*912701f9SAndroid Build Coastguard Worker $_ = <IN>; # Read comment or branches: line 1277*912701f9SAndroid Build Coastguard Worker $_ = <IN> if (/^branches:/); # Read line after branches: 1278*912701f9SAndroid Build Coastguard Worker my $id; 1279*912701f9SAndroid Build Coastguard Worker if (/^\s*jitterbug\s+0*(\d+)/i) { 1280*912701f9SAndroid Build Coastguard Worker $id = $1; 1281*912701f9SAndroid Build Coastguard Worker $TAGSCAN_WHY{$id}->{$relFile} = 1; 1282*912701f9SAndroid Build Coastguard Worker } else { 1283*912701f9SAndroid Build Coastguard Worker push @NO_JITTERBUG_FILES, [$relFile, $rev, $_] 1284*912701f9SAndroid Build Coastguard Worker if (noJitterbugFilter($rev, $date)); 1285*912701f9SAndroid Build Coastguard Worker $id = $NO_JITTERBUG; 1286*912701f9SAndroid Build Coastguard Worker } 1287*912701f9SAndroid Build Coastguard Worker $TAGSCAN_IDS{$id} = 1; 1288*912701f9SAndroid Build Coastguard Worker last unless (%revs); 1289*912701f9SAndroid Build Coastguard Worker } 1290*912701f9SAndroid Build Coastguard Worker } else { 1291*912701f9SAndroid Build Coastguard Worker cantParse('revision', $relFile, $_); 1292*912701f9SAndroid Build Coastguard Worker last; # This is very bad - bail out 1293*912701f9SAndroid Build Coastguard Worker } 1294*912701f9SAndroid Build Coastguard Worker } 1295*912701f9SAndroid Build Coastguard Worker } 1296*912701f9SAndroid Build Coastguard Worker } 1297*912701f9SAndroid Build Coastguard Worker 1298*912701f9SAndroid Build Coastguard Worker else { 1299*912701f9SAndroid Build Coastguard Worker # Tags on different branches 1300*912701f9SAndroid Build Coastguard Worker push @BRANCHED_FILES, [$relFile, $rev_lo, $rev_hi]; 1301*912701f9SAndroid Build Coastguard Worker } 1302*912701f9SAndroid Build Coastguard Worker 1303*912701f9SAndroid Build Coastguard Worker close(IN); 1304*912701f9SAndroid Build Coastguard Worker my $a = \@result; 1305*912701f9SAndroid Build Coastguard Worker 1306*912701f9SAndroid Build Coastguard Worker foreach my $revision (@$a) { 1307*912701f9SAndroid Build Coastguard Worker # $revision->[ revision, jitterbug ID, date: line ] 1308*912701f9SAndroid Build Coastguard Worker $TAGSCAN_IDS{$revision->[1]} = 1; 1309*912701f9SAndroid Build Coastguard Worker $TAGSCAN_WHY{$revision->[1]}->{$relFile} = 1; 1310*912701f9SAndroid Build Coastguard Worker } 1311*912701f9SAndroid Build Coastguard Worker 1312*912701f9SAndroid Build Coastguard Worker if (@$a) { 1313*912701f9SAndroid Build Coastguard Worker # Record latest date corresponding to HI tag 1314*912701f9SAndroid Build Coastguard Worker if ($a->[0]->[2] =~ /^date: (.+?);/) { 1315*912701f9SAndroid Build Coastguard Worker $TAGSCAN_TAG_HI_DATE = $1 1316*912701f9SAndroid Build Coastguard Worker if ($TAGSCAN_TAG_HI_DATE lt $1); 1317*912701f9SAndroid Build Coastguard Worker } else { 1318*912701f9SAndroid Build Coastguard Worker cantParse('date', $relFile, $a->[0]->[2], $a->[0]->[0]); 1319*912701f9SAndroid Build Coastguard Worker } 1320*912701f9SAndroid Build Coastguard Worker } 1321*912701f9SAndroid Build Coastguard Worker} 1322*912701f9SAndroid Build Coastguard Worker 1323*912701f9SAndroid Build Coastguard Worker###################################################################### 1324*912701f9SAndroid Build Coastguard Worker# dcuthelp 1325*912701f9SAndroid Build Coastguard Worker###################################################################### 1326*912701f9SAndroid Build Coastguard Worker 1327*912701f9SAndroid Build Coastguard Worker# Perform a "dcuthelp" and emit the results. 1328*912701f9SAndroid Build Coastguard Workersub do_dcuthelp { 1329*912701f9SAndroid Build Coastguard Worker $DCUTHELP_TAG = expandTag($QUERY->param('dcut_tag')); 1330*912701f9SAndroid Build Coastguard Worker my $ids = $QUERY->param('dcut_ids'); 1331*912701f9SAndroid Build Coastguard Worker my $user = $QUERY->param('user'); 1332*912701f9SAndroid Build Coastguard Worker 1333*912701f9SAndroid Build Coastguard Worker # Process the ID list; create a hash of IDs in %DCUTHELP_IDS 1334*912701f9SAndroid Build Coastguard Worker $ids =~ s/,/ /g; 1335*912701f9SAndroid Build Coastguard Worker my @ids = grep { /\S/ } split(/\s+/, $ids); 1336*912701f9SAndroid Build Coastguard Worker my @bogus = grep { !/^\d+$/ } @ids; 1337*912701f9SAndroid Build Coastguard Worker if (@bogus) { 1338*912701f9SAndroid Build Coastguard Worker print "These are not valid Jitterbug IDs: ", join(", ", @bogus); 1339*912701f9SAndroid Build Coastguard Worker return; 1340*912701f9SAndroid Build Coastguard Worker } 1341*912701f9SAndroid Build Coastguard Worker foreach my $id (@ids) { 1342*912701f9SAndroid Build Coastguard Worker local $_ = $id; 1343*912701f9SAndroid Build Coastguard Worker s/^0+//; 1344*912701f9SAndroid Build Coastguard Worker if (!$_) { print "0 is not a valid Jitterbug ID."; return; } 1345*912701f9SAndroid Build Coastguard Worker if (exists $DCUTHELP_IDS{$_}) { print "$id is duplicated in the Jitterbug ID list."; return; } 1346*912701f9SAndroid Build Coastguard Worker $DCUTHELP_IDS{$_} = 1; 1347*912701f9SAndroid Build Coastguard Worker } 1348*912701f9SAndroid Build Coastguard Worker 1349*912701f9SAndroid Build Coastguard Worker if ($DCUTHELP_TAG!~/\S/ || 0==scalar keys %DCUTHELP_IDS) { 1350*912701f9SAndroid Build Coastguard Worker print "Please enter a CVS tag and list of Jitterbug IDs and try again."; 1351*912701f9SAndroid Build Coastguard Worker return; 1352*912701f9SAndroid Build Coastguard Worker } 1353*912701f9SAndroid Build Coastguard Worker 1354*912701f9SAndroid Build Coastguard Worker my @m; 1355*912701f9SAndroid Build Coastguard Worker return if (!parseMod(\@m)); # what modules are we searching? 1356*912701f9SAndroid Build Coastguard Worker 1357*912701f9SAndroid Build Coastguard Worker # Announce our intentions 1358*912701f9SAndroid Build Coastguard Worker print "Performing a DCUT check in module(s) <B>", join(", ", @m) 1359*912701f9SAndroid Build Coastguard Worker , "</B> against tag <B>", tagLink($DCUTHELP_TAG,$m[0],'grepj_2'), 1360*912701f9SAndroid Build Coastguard Worker "</B>"; 1361*912701f9SAndroid Build Coastguard Worker print " with Jitterbug IDs <B>"; 1362*912701f9SAndroid Build Coastguard Worker print join(", ", 1363*912701f9SAndroid Build Coastguard Worker map {jitterbugLink($user, $_, 'grepj_2')} 1364*912701f9SAndroid Build Coastguard Worker sort {$a<=>$b} keys %DCUTHELP_IDS) 1365*912701f9SAndroid Build Coastguard Worker , "</B>"; 1366*912701f9SAndroid Build Coastguard Worker print ".\n"; 1367*912701f9SAndroid Build Coastguard Worker 1368*912701f9SAndroid Build Coastguard Worker foreach (@m) { 1369*912701f9SAndroid Build Coastguard Worker updateCacheDir($_); 1370*912701f9SAndroid Build Coastguard Worker } 1371*912701f9SAndroid Build Coastguard Worker 1372*912701f9SAndroid Build Coastguard Worker if ($UPDATE_COUNT) { 1373*912701f9SAndroid Build Coastguard Worker print "done ($UPDATE_NONATTIC_COUNT,$UPDATE_ATTIC_COUNT)."; 1374*912701f9SAndroid Build Coastguard Worker } 1375*912701f9SAndroid Build Coastguard Worker 1376*912701f9SAndroid Build Coastguard Worker $DCUTHELP_COUNT = 0; 1377*912701f9SAndroid Build Coastguard Worker print "<HR>Scanning CVS tree..."; 1378*912701f9SAndroid Build Coastguard Worker foreach (@m) { 1379*912701f9SAndroid Build Coastguard Worker dcuthelpDir($_); 1380*912701f9SAndroid Build Coastguard Worker } 1381*912701f9SAndroid Build Coastguard Worker print "done."; 1382*912701f9SAndroid Build Coastguard Worker 1383*912701f9SAndroid Build Coastguard Worker if (@NO_JITTERBUG_FILES) { 1384*912701f9SAndroid Build Coastguard Worker print "<HR>The following revisions have no associated Jitterbug, or the bug number could not be parsed from the checkin comment.\n"; 1385*912701f9SAndroid Build Coastguard Worker print "Checkins older than a year are not listed.\n"; 1386*912701f9SAndroid Build Coastguard Worker print "<BLOCKQUOTE>"; 1387*912701f9SAndroid Build Coastguard Worker print join("<BR>\n", 1388*912701f9SAndroid Build Coastguard Worker map {logLink($_->[0],'grepj_2') . 1389*912701f9SAndroid Build Coastguard Worker ", " . $_->[1] . "<BR><CODE>" . 1390*912701f9SAndroid Build Coastguard Worker $_->[2] . "</CODE>"} 1391*912701f9SAndroid Build Coastguard Worker @NO_JITTERBUG_FILES); 1392*912701f9SAndroid Build Coastguard Worker print "</BLOCKQUOTE>\n"; 1393*912701f9SAndroid Build Coastguard Worker } 1394*912701f9SAndroid Build Coastguard Worker 1395*912701f9SAndroid Build Coastguard Worker my %tagless; 1396*912701f9SAndroid Build Coastguard Worker if (@TAGLESS_FILES) { 1397*912701f9SAndroid Build Coastguard Worker print "<HR><EM>The following ", scalar @TAGLESS_FILES 1398*912701f9SAndroid Build Coastguard Worker , " files are missing the tag <B>" 1399*912701f9SAndroid Build Coastguard Worker , $DCUTHELP_TAG, "</B>. They were treated as if the tag existed " 1400*912701f9SAndroid Build Coastguard Worker , "on the initial revision.</EM>\n<BLOCKQUOTE>"; 1401*912701f9SAndroid Build Coastguard Worker print join("<BR>\n", 1402*912701f9SAndroid Build Coastguard Worker map {logLink($_, 'grepj_2')} 1403*912701f9SAndroid Build Coastguard Worker @TAGLESS_FILES); 1404*912701f9SAndroid Build Coastguard Worker print "</BLOCKQUOTE>\n"; 1405*912701f9SAndroid Build Coastguard Worker for my $f (@TAGLESS_FILES) { $tagless{$f} = 1; } 1406*912701f9SAndroid Build Coastguard Worker } 1407*912701f9SAndroid Build Coastguard Worker 1408*912701f9SAndroid Build Coastguard Worker if (@BRANCHED_FILES) { 1409*912701f9SAndroid Build Coastguard Worker print "<HR><EM><B>Error: The following ", scalar @BRANCHED_FILES 1410*912701f9SAndroid Build Coastguard Worker , " files contain the listed bug changes on different " 1411*912701f9SAndroid Build Coastguard Worker , " branches.\n</B></EM><BLOCKQUOTE>"; 1412*912701f9SAndroid Build Coastguard Worker print join("<BR>\n", 1413*912701f9SAndroid Build Coastguard Worker map {logLink($_->[0],'grepj_2') . 1414*912701f9SAndroid Build Coastguard Worker ": " . $_->[1] . ", " . $_->[2]} 1415*912701f9SAndroid Build Coastguard Worker @BRANCHED_FILES) 1416*912701f9SAndroid Build Coastguard Worker , "</BLOCKQUOTE>\n"; 1417*912701f9SAndroid Build Coastguard Worker } 1418*912701f9SAndroid Build Coastguard Worker 1419*912701f9SAndroid Build Coastguard Worker if (@DCUTHELP_BADFILES) { 1420*912701f9SAndroid Build Coastguard Worker print "<HR><EM><B>Error: The following " 1421*912701f9SAndroid Build Coastguard Worker , scalar @DCUTHELP_BADFILES, 1422*912701f9SAndroid Build Coastguard Worker " files contain intermingled bug fixes not specified in the list.", 1423*912701f9SAndroid Build Coastguard Worker "</B></EM>\n<BLOCKQUOTE>"; 1424*912701f9SAndroid Build Coastguard Worker my %badids; 1425*912701f9SAndroid Build Coastguard Worker foreach (@DCUTHELP_BADFILES) { 1426*912701f9SAndroid Build Coastguard Worker my $relFile = $_->[0]; 1427*912701f9SAndroid Build Coastguard Worker my $ids = $_->[1]; 1428*912701f9SAndroid Build Coastguard Worker print logLink($relFile, 'grepj_2'), ": " 1429*912701f9SAndroid Build Coastguard Worker , join(", ", 1430*912701f9SAndroid Build Coastguard Worker map {jitterbugLink($user, $_, 'grepj_2')} 1431*912701f9SAndroid Build Coastguard Worker @$ids) 1432*912701f9SAndroid Build Coastguard Worker , "<BR>\n"; 1433*912701f9SAndroid Build Coastguard Worker foreach my $i (@$ids) { $badids{$i} = 1; } 1434*912701f9SAndroid Build Coastguard Worker } 1435*912701f9SAndroid Build Coastguard Worker print "</BLOCKQUOTE>\n"; 1436*912701f9SAndroid Build Coastguard Worker print "Jitterbug changes not in the list: " 1437*912701f9SAndroid Build Coastguard Worker , join(", ", 1438*912701f9SAndroid Build Coastguard Worker map {jitterbugLink($user, $_, 'grepj_2')} 1439*912701f9SAndroid Build Coastguard Worker sort {$a<=>$b} keys %badids) 1440*912701f9SAndroid Build Coastguard Worker , "\n"; 1441*912701f9SAndroid Build Coastguard Worker } 1442*912701f9SAndroid Build Coastguard Worker 1443*912701f9SAndroid Build Coastguard Worker if (@DCUTHELP_RETAGS) { 1444*912701f9SAndroid Build Coastguard Worker print "<HR>CVS commands to update the tags in files containing " 1445*912701f9SAndroid Build Coastguard Worker ,"only the listed bugs (copy & paste into a shell window)."; 1446*912701f9SAndroid Build Coastguard Worker if (@DCUTHELP_BADFILES || @BRANCHED_FILES) { 1447*912701f9SAndroid Build Coastguard Worker print "<B>WARNING! Some files (see above) contain other bug changes! Files below are all \"legal\" but you may wish to address above problems before retagging.</B>"; 1448*912701f9SAndroid Build Coastguard Worker } 1449*912701f9SAndroid Build Coastguard Worker print "<BR><BR><CODE><FONT SIZE=-1>"; 1450*912701f9SAndroid Build Coastguard Worker print "cd $CVSROOT<BR>\n"; 1451*912701f9SAndroid Build Coastguard Worker # Two passes, one for normal files, another for tagless 1452*912701f9SAndroid Build Coastguard Worker my $tagless_count = 0; 1453*912701f9SAndroid Build Coastguard Worker for (my $pass=0; $pass<2; ++$pass) { 1454*912701f9SAndroid Build Coastguard Worker print "<FONT COLOR=\"#0000FF\"># The following files do not contain the tag $DCUTHELP_TAG<BR>\n" if ($pass); 1455*912701f9SAndroid Build Coastguard Worker foreach (@DCUTHELP_RETAGS) { 1456*912701f9SAndroid Build Coastguard Worker my $relFile = $_->[0]; 1457*912701f9SAndroid Build Coastguard Worker if ($pass == 0) { 1458*912701f9SAndroid Build Coastguard Worker if ($tagless{$relFile}) { 1459*912701f9SAndroid Build Coastguard Worker ++$tagless_count; 1460*912701f9SAndroid Build Coastguard Worker next; 1461*912701f9SAndroid Build Coastguard Worker } 1462*912701f9SAndroid Build Coastguard Worker } else { 1463*912701f9SAndroid Build Coastguard Worker next unless ($tagless{$relFile}); 1464*912701f9SAndroid Build Coastguard Worker } 1465*912701f9SAndroid Build Coastguard Worker my $rev_hi = $_->[1]; 1466*912701f9SAndroid Build Coastguard Worker $relFile =~ s/,v$//; 1467*912701f9SAndroid Build Coastguard Worker my $onBranch = ($rev_hi =~ /\d+\.\d+\.\d+/); 1468*912701f9SAndroid Build Coastguard Worker print "<FONT COLOR=\"#FF0000\">" if ($onBranch); 1469*912701f9SAndroid Build Coastguard Worker print "cvs tag -F -r $rev_hi $DCUTHELP_TAG $relFile"; 1470*912701f9SAndroid Build Coastguard Worker print "</FONT>" if ($onBranch); 1471*912701f9SAndroid Build Coastguard Worker print "<BR>\n"; 1472*912701f9SAndroid Build Coastguard Worker } 1473*912701f9SAndroid Build Coastguard Worker last unless ($tagless_count); 1474*912701f9SAndroid Build Coastguard Worker print "</FONT>\n" if ($pass); 1475*912701f9SAndroid Build Coastguard Worker } 1476*912701f9SAndroid Build Coastguard Worker print "</FONT></CODE>"; 1477*912701f9SAndroid Build Coastguard Worker } else { 1478*912701f9SAndroid Build Coastguard Worker print "<HR>Nothing to do; no clean checkins for bugs " 1479*912701f9SAndroid Build Coastguard Worker , join(", ", 1480*912701f9SAndroid Build Coastguard Worker map {jitterbugLink($user, $_, 'grepj_2')} 1481*912701f9SAndroid Build Coastguard Worker sort {$a<=>$b} keys %DCUTHELP_IDS) 1482*912701f9SAndroid Build Coastguard Worker , " after " 1483*912701f9SAndroid Build Coastguard Worker , tagLink($DCUTHELP_TAG,$m[0],'grepj_2') 1484*912701f9SAndroid Build Coastguard Worker , " in module(s) <B>" 1485*912701f9SAndroid Build Coastguard Worker , join(", ", @m), "</B>.\n" 1486*912701f9SAndroid Build Coastguard Worker ; 1487*912701f9SAndroid Build Coastguard Worker } 1488*912701f9SAndroid Build Coastguard Worker} 1489*912701f9SAndroid Build Coastguard Worker 1490*912701f9SAndroid Build Coastguard Worker# Given a relative path to $CVSROOT, dcuthelp the 1491*912701f9SAndroid Build Coastguard Worker# corresponding item under $CACHE. Path may point to a 1492*912701f9SAndroid Build Coastguard Worker# file or a directory. 1493*912701f9SAndroid Build Coastguard Worker# @param relative directory, not ending in "/", e.g. "icu/icu" 1494*912701f9SAndroid Build Coastguard Worker# @param item name in that directory 1495*912701f9SAndroid Build Coastguard Workersub dcuthelpEntry { 1496*912701f9SAndroid Build Coastguard Worker my $relDir = shift; 1497*912701f9SAndroid Build Coastguard Worker my $item = shift; # A file or dir in $CVSROOT/$relDir 1498*912701f9SAndroid Build Coastguard Worker 1499*912701f9SAndroid Build Coastguard Worker # Ignore stuff in the Attic 1500*912701f9SAndroid Build Coastguard Worker return if ($item eq 'Attic'); 1501*912701f9SAndroid Build Coastguard Worker 1502*912701f9SAndroid Build Coastguard Worker if (-d "$CACHE/$relDir/$item") { 1503*912701f9SAndroid Build Coastguard Worker dcuthelpDir("$relDir/$item"); 1504*912701f9SAndroid Build Coastguard Worker } elsif ($item =~ /,v$/) { 1505*912701f9SAndroid Build Coastguard Worker dcuthelpFile("$relDir/$item"); 1506*912701f9SAndroid Build Coastguard Worker } 1507*912701f9SAndroid Build Coastguard Worker} 1508*912701f9SAndroid Build Coastguard Worker 1509*912701f9SAndroid Build Coastguard Worker# Given a relative directory path to $CACHE, dcuthelp the 1510*912701f9SAndroid Build Coastguard Worker# underlying files. 1511*912701f9SAndroid Build Coastguard Worker# @param relative directory, not ending in "/", e.g. "icu/icu" 1512*912701f9SAndroid Build Coastguard Workersub dcuthelpDir { 1513*912701f9SAndroid Build Coastguard Worker my $relDir = shift; 1514*912701f9SAndroid Build Coastguard Worker 1515*912701f9SAndroid Build Coastguard Worker debugOut("dcuthelpDir($relDir)") if ($DEBUG); 1516*912701f9SAndroid Build Coastguard Worker 1517*912701f9SAndroid Build Coastguard Worker my $cacheDir = "$CACHE/$relDir"; 1518*912701f9SAndroid Build Coastguard Worker 1519*912701f9SAndroid Build Coastguard Worker # First dcuthelp files in this directory 1520*912701f9SAndroid Build Coastguard Worker opendir(DIR, $cacheDir); 1521*912701f9SAndroid Build Coastguard Worker my @cacheList = grep !/^\.\.?$/, readdir(DIR); 1522*912701f9SAndroid Build Coastguard Worker closedir(DIR); 1523*912701f9SAndroid Build Coastguard Worker 1524*912701f9SAndroid Build Coastguard Worker # Dcuthelp each individual entry 1525*912701f9SAndroid Build Coastguard Worker foreach (@cacheList) { 1526*912701f9SAndroid Build Coastguard Worker dcuthelpEntry($relDir, $_); 1527*912701f9SAndroid Build Coastguard Worker } 1528*912701f9SAndroid Build Coastguard Worker} 1529*912701f9SAndroid Build Coastguard Worker 1530*912701f9SAndroid Build Coastguard Worker# Given a relative file path to $CVSROOT, dcuthelp the 1531*912701f9SAndroid Build Coastguard Worker# corresponding file under $CACHE. 1532*912701f9SAndroid Build Coastguard Worker# @param relative file path 1533*912701f9SAndroid Build Coastguard Workersub dcuthelpFile { 1534*912701f9SAndroid Build Coastguard Worker my $relFile = shift; 1535*912701f9SAndroid Build Coastguard Worker 1536*912701f9SAndroid Build Coastguard Worker # Display progress; it takes awhile 1537*912701f9SAndroid Build Coastguard Worker if (++$DCUTHELP_COUNT % 100 == 0) { 1538*912701f9SAndroid Build Coastguard Worker print " $DCUTHELP_COUNT..."; 1539*912701f9SAndroid Build Coastguard Worker } 1540*912701f9SAndroid Build Coastguard Worker 1541*912701f9SAndroid Build Coastguard Worker # This file contains the output of rlog. 1542*912701f9SAndroid Build Coastguard Worker my $file = "$CACHE/$relFile"; 1543*912701f9SAndroid Build Coastguard Worker 1544*912701f9SAndroid Build Coastguard Worker # Parse the rlog file. Start by extracting the tag names. Look 1545*912701f9SAndroid Build Coastguard Worker # for the DCUTHELP_TAG and its associated revision 1546*912701f9SAndroid Build Coastguard Worker # number. 1547*912701f9SAndroid Build Coastguard Worker open(IN, $file); 1548*912701f9SAndroid Build Coastguard Worker while (<IN>) { 1549*912701f9SAndroid Build Coastguard Worker last if (/^symbolic names:\s*$/); 1550*912701f9SAndroid Build Coastguard Worker } 1551*912701f9SAndroid Build Coastguard Worker my $rev_tag = ''; 1552*912701f9SAndroid Build Coastguard Worker while (<IN>) { 1553*912701f9SAndroid Build Coastguard Worker last if (/^\S/); 1554*912701f9SAndroid Build Coastguard Worker if (/^\s+$DCUTHELP_TAG:\s*(\S+)/) { 1555*912701f9SAndroid Build Coastguard Worker $rev_tag = $1; 1556*912701f9SAndroid Build Coastguard Worker last; 1557*912701f9SAndroid Build Coastguard Worker } 1558*912701f9SAndroid Build Coastguard Worker } 1559*912701f9SAndroid Build Coastguard Worker 1560*912701f9SAndroid Build Coastguard Worker # Check for dead files. Look ahead and find the state of the head 1561*912701f9SAndroid Build Coastguard Worker # revision. 1562*912701f9SAndroid Build Coastguard Worker my $pos = tell(IN); 1563*912701f9SAndroid Build Coastguard Worker my $state = ''; 1564*912701f9SAndroid Build Coastguard Worker while (<IN>) { 1565*912701f9SAndroid Build Coastguard Worker if (/^date:.+state: ([A-Za-z]+)/) { 1566*912701f9SAndroid Build Coastguard Worker $state = $1; 1567*912701f9SAndroid Build Coastguard Worker last; 1568*912701f9SAndroid Build Coastguard Worker } 1569*912701f9SAndroid Build Coastguard Worker } 1570*912701f9SAndroid Build Coastguard Worker seek(IN,$pos,0); 1571*912701f9SAndroid Build Coastguard Worker 1572*912701f9SAndroid Build Coastguard Worker # If this file is 'dead', we're done. 1573*912701f9SAndroid Build Coastguard Worker return if ($state eq 'dead'); 1574*912701f9SAndroid Build Coastguard Worker 1575*912701f9SAndroid Build Coastguard Worker # If the tag is missing, record the fact. Continue to process 1576*912701f9SAndroid Build Coastguard Worker # the file as if the tag existed on the earliest revision. 1577*912701f9SAndroid Build Coastguard Worker # This allows the tagging of newly added files. 1578*912701f9SAndroid Build Coastguard Worker if (!$rev_tag) { 1579*912701f9SAndroid Build Coastguard Worker push @TAGLESS_FILES, $relFile; 1580*912701f9SAndroid Build Coastguard Worker } 1581*912701f9SAndroid Build Coastguard Worker 1582*912701f9SAndroid Build Coastguard Worker # I'm going to assume the rlog output (the CACHE file) contains a series 1583*912701f9SAndroid Build Coastguard Worker # of groups of lines, like so: 1584*912701f9SAndroid Build Coastguard Worker #|---------------------------- 1585*912701f9SAndroid Build Coastguard Worker #|revision 1.40 1586*912701f9SAndroid Build Coastguard Worker #|date: 2001/08/02 18:24:58; author: grhoten; state: Exp; lines: +82 -73 1587*912701f9SAndroid Build Coastguard Worker #|jitterbug 1080: general readme.html updates 1588*912701f9SAndroid Build Coastguard Worker # That is, the first line has the revision #. 1589*912701f9SAndroid Build Coastguard Worker # The third line has the bug ID. Sometimes the third line has a 1590*912701f9SAndroid Build Coastguard Worker # branch field. 1591*912701f9SAndroid Build Coastguard Worker 1592*912701f9SAndroid Build Coastguard Worker # Find bug IDs later than the given tag, and record any that aren't 1593*912701f9SAndroid Build Coastguard Worker # on the allowed list. Locate $rev_hi - the high 1594*912701f9SAndroid Build Coastguard Worker # revision of any bug found in the list. 1595*912701f9SAndroid Build Coastguard Worker my @problem_ids; # Bug IDs between $rev_tag and $rev_hi not in the list 1596*912701f9SAndroid Build Coastguard Worker my $rev_hi; 1597*912701f9SAndroid Build Coastguard Worker my $bottom_rev = ''; # Last revision in the file 1598*912701f9SAndroid Build Coastguard Worker while (<IN>) { 1599*912701f9SAndroid Build Coastguard Worker if (/^-{20,}$/) { 1600*912701f9SAndroid Build Coastguard Worker $_ = <IN>; # Read revision line 1601*912701f9SAndroid Build Coastguard Worker if (/revision (\S+)/) { 1602*912701f9SAndroid Build Coastguard Worker my $rev = $1; 1603*912701f9SAndroid Build Coastguard Worker $bottom_rev = $rev; 1604*912701f9SAndroid Build Coastguard Worker if ($rev eq $rev_tag) { 1605*912701f9SAndroid Build Coastguard Worker # Scan remainder of file to record last rev 1606*912701f9SAndroid Build Coastguard Worker while (<IN>) { 1607*912701f9SAndroid Build Coastguard Worker if (/^-{20,}$/) { 1608*912701f9SAndroid Build Coastguard Worker $_ = <IN>; # Read revision line 1609*912701f9SAndroid Build Coastguard Worker $bottom_rev = $1 if (/revision (\S+)/); 1610*912701f9SAndroid Build Coastguard Worker } 1611*912701f9SAndroid Build Coastguard Worker } 1612*912701f9SAndroid Build Coastguard Worker last; 1613*912701f9SAndroid Build Coastguard Worker } 1614*912701f9SAndroid Build Coastguard Worker my $date = <IN>; # Read date line 1615*912701f9SAndroid Build Coastguard Worker $_ = <IN>; # Read comment or branches: line 1616*912701f9SAndroid Build Coastguard Worker $_ = <IN> if (/^branches:/); # Read line after branches: 1617*912701f9SAndroid Build Coastguard Worker my $id; 1618*912701f9SAndroid Build Coastguard Worker if (/^\s*jitterbug\s+0*(\d+)/i) { 1619*912701f9SAndroid Build Coastguard Worker $id = $1; 1620*912701f9SAndroid Build Coastguard Worker } else { 1621*912701f9SAndroid Build Coastguard Worker push @NO_JITTERBUG_FILES, [$relFile, $rev, $_] 1622*912701f9SAndroid Build Coastguard Worker if (noJitterbugFilter($rev, $date)); 1623*912701f9SAndroid Build Coastguard Worker $id = $NO_JITTERBUG; 1624*912701f9SAndroid Build Coastguard Worker } 1625*912701f9SAndroid Build Coastguard Worker my $in_list = (exists $DCUTHELP_IDS{$id}); 1626*912701f9SAndroid Build Coastguard Worker# # Handle tagless files a little differently 1627*912701f9SAndroid Build Coastguard Worker# if (!$rev_tag) { 1628*912701f9SAndroid Build Coastguard Worker# if (!$rev_hi) { 1629*912701f9SAndroid Build Coastguard Worker# if ($in_list) { 1630*912701f9SAndroid Build Coastguard Worker# $rev_hi = $rev; 1631*912701f9SAndroid Build Coastguard Worker# } else { 1632*912701f9SAndroid Build Coastguard Worker# } 1633*912701f9SAndroid Build Coastguard Worker# } 1634*912701f9SAndroid Build Coastguard Worker# 1635*912701f9SAndroid Build Coastguard Worker# } 1636*912701f9SAndroid Build Coastguard Worker if (!$rev_hi) { 1637*912701f9SAndroid Build Coastguard Worker if ($in_list) { 1638*912701f9SAndroid Build Coastguard Worker $rev_hi = $rev; 1639*912701f9SAndroid Build Coastguard Worker } 1640*912701f9SAndroid Build Coastguard Worker } else { 1641*912701f9SAndroid Build Coastguard Worker if (!$in_list) { 1642*912701f9SAndroid Build Coastguard Worker push @problem_ids, $id; 1643*912701f9SAndroid Build Coastguard Worker } 1644*912701f9SAndroid Build Coastguard Worker } 1645*912701f9SAndroid Build Coastguard Worker } else { 1646*912701f9SAndroid Build Coastguard Worker cantParse('revision', $relFile, $_); 1647*912701f9SAndroid Build Coastguard Worker } 1648*912701f9SAndroid Build Coastguard Worker } 1649*912701f9SAndroid Build Coastguard Worker } 1650*912701f9SAndroid Build Coastguard Worker 1651*912701f9SAndroid Build Coastguard Worker # If the bottom revision looks like a branch, then we need 1652*912701f9SAndroid Build Coastguard Worker # to do extra processing. Branch revisions are listed at the 1653*912701f9SAndroid Build Coastguard Worker # end of the rlog output. 1654*912701f9SAndroid Build Coastguard Worker if ($bottom_rev =~ /\d+\.\d+\.\d+\.\d+/ && 1655*912701f9SAndroid Build Coastguard Worker $bottom_rev ne '1.1.1.1') { 1656*912701f9SAndroid Build Coastguard Worker 1657*912701f9SAndroid Build Coastguard Worker # This file contains branches; do special handling 1658*912701f9SAndroid Build Coastguard Worker 1659*912701f9SAndroid Build Coastguard Worker # Parse all the revisions and form a branch tree. 1660*912701f9SAndroid Build Coastguard Worker # Construct a hash (%tree) of revision numbers to jitterbugs. 1661*912701f9SAndroid Build Coastguard Worker # In addition, "$rev-" maps to a ref to an array of branches, 1662*912701f9SAndroid Build Coastguard Worker # if any. 1663*912701f9SAndroid Build Coastguard Worker my %tree; 1664*912701f9SAndroid Build Coastguard Worker seek(IN,0,0); # rewind to start 1665*912701f9SAndroid Build Coastguard Worker while (<IN>) { 1666*912701f9SAndroid Build Coastguard Worker if (/^-{20,}$/) { 1667*912701f9SAndroid Build Coastguard Worker $_ = <IN>; # Read revision line 1668*912701f9SAndroid Build Coastguard Worker if (/revision (\S+)/) { 1669*912701f9SAndroid Build Coastguard Worker my $rev = $1; 1670*912701f9SAndroid Build Coastguard Worker my $date = <IN>; # Read date line 1671*912701f9SAndroid Build Coastguard Worker $_ = <IN>; # Read comment or branches: line 1672*912701f9SAndroid Build Coastguard Worker if (/^branches:\s*(.*)/) { 1673*912701f9SAndroid Build Coastguard Worker my @branches = split(/;\s*/, $1); 1674*912701f9SAndroid Build Coastguard Worker $tree{$rev . '-'} = \@branches; 1675*912701f9SAndroid Build Coastguard Worker $_ = <IN>; # Read comment line 1676*912701f9SAndroid Build Coastguard Worker } 1677*912701f9SAndroid Build Coastguard Worker my $id; 1678*912701f9SAndroid Build Coastguard Worker if (/^\s*jitterbug\s+0*(\d+)/i) { 1679*912701f9SAndroid Build Coastguard Worker $id = $1; 1680*912701f9SAndroid Build Coastguard Worker } else { 1681*912701f9SAndroid Build Coastguard Worker push @NO_JITTERBUG_FILES, [$relFile, $rev, $_] 1682*912701f9SAndroid Build Coastguard Worker if (noJitterbugFilter($rev, $date)); 1683*912701f9SAndroid Build Coastguard Worker $id = $NO_JITTERBUG; 1684*912701f9SAndroid Build Coastguard Worker } 1685*912701f9SAndroid Build Coastguard Worker $tree{$rev} = $id; 1686*912701f9SAndroid Build Coastguard Worker } else { 1687*912701f9SAndroid Build Coastguard Worker cantParse('revision', $relFile, $_); 1688*912701f9SAndroid Build Coastguard Worker } 1689*912701f9SAndroid Build Coastguard Worker } 1690*912701f9SAndroid Build Coastguard Worker } 1691*912701f9SAndroid Build Coastguard Worker 1692*912701f9SAndroid Build Coastguard Worker# print "[$relFile: "; 1693*912701f9SAndroid Build Coastguard Worker# print join("; ", 1694*912701f9SAndroid Build Coastguard Worker# map {$_ . " => " . 1695*912701f9SAndroid Build Coastguard Worker# (ref($tree{$_}) 1696*912701f9SAndroid Build Coastguard Worker# ?("(".join(",",@{$tree{$_}}).")") 1697*912701f9SAndroid Build Coastguard Worker# :$tree{$_})} 1698*912701f9SAndroid Build Coastguard Worker# sort keys %tree); 1699*912701f9SAndroid Build Coastguard Worker 1700*912701f9SAndroid Build Coastguard Worker $rev_hi = dcuthelpScan(\%tree, $rev_tag, 1); 1701*912701f9SAndroid Build Coastguard Worker 1702*912701f9SAndroid Build Coastguard Worker# print ": scan=>$rev_hi]"; 1703*912701f9SAndroid Build Coastguard Worker 1704*912701f9SAndroid Build Coastguard Worker @problem_ids = (); 1705*912701f9SAndroid Build Coastguard Worker if ($rev_hi =~ /;/) { 1706*912701f9SAndroid Build Coastguard Worker # Tags on different branches 1707*912701f9SAndroid Build Coastguard Worker my @a = split(/;/, $rev_hi); 1708*912701f9SAndroid Build Coastguard Worker unshift @a, $relFile; 1709*912701f9SAndroid Build Coastguard Worker push @BRANCHED_FILES, \@a; 1710*912701f9SAndroid Build Coastguard Worker return; 1711*912701f9SAndroid Build Coastguard Worker } elsif ($rev_hi) { 1712*912701f9SAndroid Build Coastguard Worker my @revs = traverseRevisions($rev_tag, $rev_hi); 1713*912701f9SAndroid Build Coastguard Worker 1714*912701f9SAndroid Build Coastguard Worker shift(@revs); # discard rev_lo 1715*912701f9SAndroid Build Coastguard Worker my %revs; 1716*912701f9SAndroid Build Coastguard Worker foreach (@revs) { $revs{$_} = 1; } # convert to hash 1717*912701f9SAndroid Build Coastguard Worker 1718*912701f9SAndroid Build Coastguard Worker seek(IN,0,0); # rewind to start 1719*912701f9SAndroid Build Coastguard Worker while (<IN>) { 1720*912701f9SAndroid Build Coastguard Worker if (/^-{20,}$/) { 1721*912701f9SAndroid Build Coastguard Worker $_ = <IN>; # Read revision line 1722*912701f9SAndroid Build Coastguard Worker if (/revision (\S+)/) { 1723*912701f9SAndroid Build Coastguard Worker my $rev = $1; 1724*912701f9SAndroid Build Coastguard Worker if (exists $revs{$rev}) { 1725*912701f9SAndroid Build Coastguard Worker delete $revs{$rev}; 1726*912701f9SAndroid Build Coastguard Worker my $date = <IN>; # Read date line 1727*912701f9SAndroid Build Coastguard Worker $_ = <IN>; # Read comment or branches: line 1728*912701f9SAndroid Build Coastguard Worker $_ = <IN> if (/^branches:/); # Read line after branches: 1729*912701f9SAndroid Build Coastguard Worker my $id; 1730*912701f9SAndroid Build Coastguard Worker if (/^\s*jitterbug\s+0*(\d+)/i) { 1731*912701f9SAndroid Build Coastguard Worker $id = $1; 1732*912701f9SAndroid Build Coastguard Worker } else { 1733*912701f9SAndroid Build Coastguard Worker push @NO_JITTERBUG_FILES, [$relFile, $rev, $_] 1734*912701f9SAndroid Build Coastguard Worker if (noJitterbugFilter($rev, $date)); 1735*912701f9SAndroid Build Coastguard Worker $id = $NO_JITTERBUG; 1736*912701f9SAndroid Build Coastguard Worker } 1737*912701f9SAndroid Build Coastguard Worker if (!exists $DCUTHELP_IDS{$id}) { 1738*912701f9SAndroid Build Coastguard Worker push @problem_ids, $id; 1739*912701f9SAndroid Build Coastguard Worker } 1740*912701f9SAndroid Build Coastguard Worker last unless (%revs); 1741*912701f9SAndroid Build Coastguard Worker } 1742*912701f9SAndroid Build Coastguard Worker } else { 1743*912701f9SAndroid Build Coastguard Worker cantParse('revision', $relFile, $_); 1744*912701f9SAndroid Build Coastguard Worker last; # This is very bad - bail out 1745*912701f9SAndroid Build Coastguard Worker } 1746*912701f9SAndroid Build Coastguard Worker } 1747*912701f9SAndroid Build Coastguard Worker } 1748*912701f9SAndroid Build Coastguard Worker } 1749*912701f9SAndroid Build Coastguard Worker } 1750*912701f9SAndroid Build Coastguard Worker 1751*912701f9SAndroid Build Coastguard Worker if (@problem_ids) { 1752*912701f9SAndroid Build Coastguard Worker my @a = sortedUniqueInts(@problem_ids); 1753*912701f9SAndroid Build Coastguard Worker push @DCUTHELP_BADFILES, [$relFile, \@a]; 1754*912701f9SAndroid Build Coastguard Worker } elsif ($rev_hi) { 1755*912701f9SAndroid Build Coastguard Worker # This file is okay; record the data needed for moving the tag 1756*912701f9SAndroid Build Coastguard Worker push @DCUTHELP_RETAGS, [$relFile, $rev_hi]; 1757*912701f9SAndroid Build Coastguard Worker } 1758*912701f9SAndroid Build Coastguard Worker 1759*912701f9SAndroid Build Coastguard Worker close(IN); 1760*912701f9SAndroid Build Coastguard Worker} 1761*912701f9SAndroid Build Coastguard Worker 1762*912701f9SAndroid Build Coastguard Worker# Given a revision tree (see dcuthelpFile), look for %DCUTHELP_IDS 1763*912701f9SAndroid Build Coastguard Worker# bugs along various branches, starting at a given revision. Proceed 1764*912701f9SAndroid Build Coastguard Worker# along the branch of the given revision by incrementing it using 1765*912701f9SAndroid Build Coastguard Worker# incRev(). If any revision along the way is a branch point, follow 1766*912701f9SAndroid Build Coastguard Worker# that branch by recursing. If found on two split branches, 1767*912701f9SAndroid Build Coastguard Worker# return 'rev;rev'. If not found at all, return ''. If found on 1768*912701f9SAndroid Build Coastguard Worker# exactly one branch, return the furthest revision at which it was 1769*912701f9SAndroid Build Coastguard Worker# found. 1770*912701f9SAndroid Build Coastguard Worker# 1771*912701f9SAndroid Build Coastguard Worker# @param tree, as created by dcuthelpFile 1772*912701f9SAndroid Build Coastguard Worker# @param first revision to examine 1773*912701f9SAndroid Build Coastguard Worker# @param if true, exclude given revision from bug search 1774*912701f9SAndroid Build Coastguard Worker# but not from branch analysis. 1775*912701f9SAndroid Build Coastguard Worker# 1776*912701f9SAndroid Build Coastguard Worker# @return either a revision, or 'rev;rev' if the bugs occur 1777*912701f9SAndroid Build Coastguard Worker# on two split branches, or '' if the bugs aren't seen. 1778*912701f9SAndroid Build Coastguard Workersub dcuthelpScan { 1779*912701f9SAndroid Build Coastguard Worker my $tree = shift; # parsed revision tree; see dcuthelpFile 1780*912701f9SAndroid Build Coastguard Worker my $rev = shift; # rev to start at 1781*912701f9SAndroid Build Coastguard Worker my $exclusive = shift || ''; # is $rev exclusive? 1782*912701f9SAndroid Build Coastguard Worker 1783*912701f9SAndroid Build Coastguard Worker# print "[scan $tree $rev $exclusive]"; 1784*912701f9SAndroid Build Coastguard Worker 1785*912701f9SAndroid Build Coastguard Worker # If there are no branches between $rev and the end of its branch, 1786*912701f9SAndroid Build Coastguard Worker # then return the top revision at which one of %DCUTHELP_IDS is seen. 1787*912701f9SAndroid Build Coastguard Worker my $branchrev = ''; # First rev at which branch was seen, if any 1788*912701f9SAndroid Build Coastguard Worker my $lastbugrev = ''; # Last rev at which bug was seen 1789*912701f9SAndroid Build Coastguard Worker my $r; 1790*912701f9SAndroid Build Coastguard Worker for ($r=$rev ;exists $tree->{$r}; $r=incRev($r)) { 1791*912701f9SAndroid Build Coastguard Worker# print "{$r}"; 1792*912701f9SAndroid Build Coastguard Worker if (exists $DCUTHELP_IDS{$tree->{$r}}) { 1793*912701f9SAndroid Build Coastguard Worker $lastbugrev = $r; 1794*912701f9SAndroid Build Coastguard Worker } 1795*912701f9SAndroid Build Coastguard Worker if (exists $tree->{"$r-"}) { 1796*912701f9SAndroid Build Coastguard Worker $branchrev = $r; 1797*912701f9SAndroid Build Coastguard Worker last; 1798*912701f9SAndroid Build Coastguard Worker } 1799*912701f9SAndroid Build Coastguard Worker } 1800*912701f9SAndroid Build Coastguard Worker 1801*912701f9SAndroid Build Coastguard Worker # If $exclusive it true, can't return this rev. 1802*912701f9SAndroid Build Coastguard Worker if ($exclusive && ($lastbugrev eq $rev)) { 1803*912701f9SAndroid Build Coastguard Worker $lastbugrev = ''; 1804*912701f9SAndroid Build Coastguard Worker } 1805*912701f9SAndroid Build Coastguard Worker 1806*912701f9SAndroid Build Coastguard Worker # If there are no branches we are done. 1807*912701f9SAndroid Build Coastguard Worker if (!$branchrev) { 1808*912701f9SAndroid Build Coastguard Worker return $lastbugrev; 1809*912701f9SAndroid Build Coastguard Worker } 1810*912701f9SAndroid Build Coastguard Worker 1811*912701f9SAndroid Build Coastguard Worker # Otherwise, examine the n branches and the continuation of 1812*912701f9SAndroid Build Coastguard Worker # this branch separately. Convert branch revisions to the first 1813*912701f9SAndroid Build Coastguard Worker # rev on each branch, e.g., "1.14.2" => "1.14.2.1" 1814*912701f9SAndroid Build Coastguard Worker my @branches = map {"$_.1"} @{$tree->{"$branchrev-"}}; 1815*912701f9SAndroid Build Coastguard Worker $r = incRev($branchrev); 1816*912701f9SAndroid Build Coastguard Worker push @branches, $r if (exists $tree->{$r}); 1817*912701f9SAndroid Build Coastguard Worker 1818*912701f9SAndroid Build Coastguard Worker $r = ''; 1819*912701f9SAndroid Build Coastguard Worker foreach (@branches) { 1820*912701f9SAndroid Build Coastguard Worker my $a = dcuthelpScan($tree, $_); 1821*912701f9SAndroid Build Coastguard Worker return $a if ($a =~ /;/); 1822*912701f9SAndroid Build Coastguard Worker if ($a) { 1823*912701f9SAndroid Build Coastguard Worker if ($r) { 1824*912701f9SAndroid Build Coastguard Worker # Our bugs were seen on more than one branch 1825*912701f9SAndroid Build Coastguard Worker return "$r;$a"; 1826*912701f9SAndroid Build Coastguard Worker } 1827*912701f9SAndroid Build Coastguard Worker $r = $a; 1828*912701f9SAndroid Build Coastguard Worker } 1829*912701f9SAndroid Build Coastguard Worker } 1830*912701f9SAndroid Build Coastguard Worker 1831*912701f9SAndroid Build Coastguard Worker # If we haven't seen it on any branches, use result up to the 1832*912701f9SAndroid Build Coastguard Worker # branch point, found above. 1833*912701f9SAndroid Build Coastguard Worker $r ||= $lastbugrev; 1834*912701f9SAndroid Build Coastguard Worker 1835*912701f9SAndroid Build Coastguard Worker return $r; 1836*912701f9SAndroid Build Coastguard Worker} 1837*912701f9SAndroid Build Coastguard Worker 1838*912701f9SAndroid Build Coastguard Worker###################################################################### 1839*912701f9SAndroid Build Coastguard Worker# CVS rlog cache 1840*912701f9SAndroid Build Coastguard Worker###################################################################### 1841*912701f9SAndroid Build Coastguard Worker 1842*912701f9SAndroid Build Coastguard Worker#--------------------------------------------------------------------- 1843*912701f9SAndroid Build Coastguard Worker# Given a relative path to $CVSROOT, update the 1844*912701f9SAndroid Build Coastguard Worker# corresponding item under $CACHE. Path may point to a 1845*912701f9SAndroid Build Coastguard Worker# file or a directory. 1846*912701f9SAndroid Build Coastguard Worker# @param relative directory, not ending in "/", e.g. "icu/icu" 1847*912701f9SAndroid Build Coastguard Worker# @param item name in that directory 1848*912701f9SAndroid Build Coastguard Workersub updateCacheEntry { 1849*912701f9SAndroid Build Coastguard Worker my $relDir = shift; 1850*912701f9SAndroid Build Coastguard Worker my $item = shift; # A file or dir in $CVSROOT/$relDir 1851*912701f9SAndroid Build Coastguard Worker 1852*912701f9SAndroid Build Coastguard Worker if (-d "$CVSROOT/$relDir/$item") { 1853*912701f9SAndroid Build Coastguard Worker updateCacheDir("$relDir/$item"); 1854*912701f9SAndroid Build Coastguard Worker } elsif ($item =~ /,v$/) { 1855*912701f9SAndroid Build Coastguard Worker updateCacheFile("$relDir/$item"); 1856*912701f9SAndroid Build Coastguard Worker } 1857*912701f9SAndroid Build Coastguard Worker} 1858*912701f9SAndroid Build Coastguard Worker 1859*912701f9SAndroid Build Coastguard Worker#--------------------------------------------------------------------- 1860*912701f9SAndroid Build Coastguard Worker# Given a relative directory path to $CVSROOT, update the 1861*912701f9SAndroid Build Coastguard Worker# corresponding directory under $CACHE. 1862*912701f9SAndroid Build Coastguard Worker# @param relative directory, not ending in "/", e.g. "icu/icu" 1863*912701f9SAndroid Build Coastguard Workersub updateCacheDir { 1864*912701f9SAndroid Build Coastguard Worker my $relDir = shift; 1865*912701f9SAndroid Build Coastguard Worker 1866*912701f9SAndroid Build Coastguard Worker debugOut("+updateCacheDir($relDir)") if ($DEBUG); 1867*912701f9SAndroid Build Coastguard Worker 1868*912701f9SAndroid Build Coastguard Worker my $cvsDir = "$CVSROOT/$relDir"; 1869*912701f9SAndroid Build Coastguard Worker my $cacheDir = "$CACHE/$relDir"; 1870*912701f9SAndroid Build Coastguard Worker 1871*912701f9SAndroid Build Coastguard Worker # First update files in this directory 1872*912701f9SAndroid Build Coastguard Worker opendir(DIR, $cvsDir); 1873*912701f9SAndroid Build Coastguard Worker my @cvsList = grep !/^\.\.?$/ && $_ ne 'CVS', readdir(DIR); 1874*912701f9SAndroid Build Coastguard Worker closedir(DIR); 1875*912701f9SAndroid Build Coastguard Worker my %cvsPruneHash; 1876*912701f9SAndroid Build Coastguard Worker foreach (@cvsList) { $cvsPruneHash{$_} = 1; } 1877*912701f9SAndroid Build Coastguard Worker if (!$QUERY->param('include_attic')) { 1878*912701f9SAndroid Build Coastguard Worker @cvsList = grep !/^attic$/i, @cvsList; 1879*912701f9SAndroid Build Coastguard Worker } 1880*912701f9SAndroid Build Coastguard Worker my %cvsHash; 1881*912701f9SAndroid Build Coastguard Worker foreach (@cvsList) { $cvsHash{$_} = 1; } 1882*912701f9SAndroid Build Coastguard Worker 1883*912701f9SAndroid Build Coastguard Worker # Update/create the cache directory. If it doesn't exist, 1884*912701f9SAndroid Build Coastguard Worker # create it. If it does, prune out any obsolete entries. 1885*912701f9SAndroid Build Coastguard Worker if (-d $cacheDir) { 1886*912701f9SAndroid Build Coastguard Worker if (!opendir(DIR, $cacheDir)) { 1887*912701f9SAndroid Build Coastguard Worker print "Can't open dir $cacheDir: $!"; 1888*912701f9SAndroid Build Coastguard Worker debugOut("-!updateCacheDir($relDir)") if ($DEBUG); 1889*912701f9SAndroid Build Coastguard Worker return; 1890*912701f9SAndroid Build Coastguard Worker } 1891*912701f9SAndroid Build Coastguard Worker my @cacheList = grep !/^\.\.?$/, readdir(DIR); 1892*912701f9SAndroid Build Coastguard Worker closedir(DIR); 1893*912701f9SAndroid Build Coastguard Worker 1894*912701f9SAndroid Build Coastguard Worker # Delete things that don't exist in CVS 1895*912701f9SAndroid Build Coastguard Worker foreach (@cacheList) { 1896*912701f9SAndroid Build Coastguard Worker if (!exists $cvsPruneHash{$_}) { 1897*912701f9SAndroid Build Coastguard Worker debugOut ( " Removing $cacheDir/$_ .." ) if ($DEBUG); 1898*912701f9SAndroid Build Coastguard Worker rmtree("$cacheDir/$_", 0, 1); 1899*912701f9SAndroid Build Coastguard Worker } 1900*912701f9SAndroid Build Coastguard Worker } 1901*912701f9SAndroid Build Coastguard Worker } else { 1902*912701f9SAndroid Build Coastguard Worker mkpath($cacheDir, 0, 0777); 1903*912701f9SAndroid Build Coastguard Worker } 1904*912701f9SAndroid Build Coastguard Worker 1905*912701f9SAndroid Build Coastguard Worker # Update each individual entry 1906*912701f9SAndroid Build Coastguard Worker foreach (@cvsList) { 1907*912701f9SAndroid Build Coastguard Worker updateCacheEntry($relDir, $_); 1908*912701f9SAndroid Build Coastguard Worker } 1909*912701f9SAndroid Build Coastguard Worker 1910*912701f9SAndroid Build Coastguard Worker debugOut("-updateCacheDir($relDir)") if ($DEBUG); 1911*912701f9SAndroid Build Coastguard Worker} 1912*912701f9SAndroid Build Coastguard Worker 1913*912701f9SAndroid Build Coastguard Worker#--------------------------------------------------------------------- 1914*912701f9SAndroid Build Coastguard Worker# Given a relative file path to $CVSROOT, update the 1915*912701f9SAndroid Build Coastguard Worker# corresponding file under $CACHE, if necessary. 1916*912701f9SAndroid Build Coastguard Worker# @param relative file path 1917*912701f9SAndroid Build Coastguard Workersub updateCacheFile { 1918*912701f9SAndroid Build Coastguard Worker my $relFile = shift; 1919*912701f9SAndroid Build Coastguard Worker 1920*912701f9SAndroid Build Coastguard Worker if (! -e "$CACHE/$relFile" || 1921*912701f9SAndroid Build Coastguard Worker (-M "$CACHE/$relFile" > -M "$CVSROOT/$relFile")) { 1922*912701f9SAndroid Build Coastguard Worker if (!$UPDATE_COUNT) { 1923*912701f9SAndroid Build Coastguard Worker print "<HR>Updating cache..."; 1924*912701f9SAndroid Build Coastguard Worker if(! -e "$CACHE/$relFile") { 1925*912701f9SAndroid Build Coastguard Worker debugOut ( " because $CACHE/$relFile was not cached.." ) if ($DEBUG); 1926*912701f9SAndroid Build Coastguard Worker } else { 1927*912701f9SAndroid Build Coastguard Worker debugOut ( " because $relFile was updated.." ) if ($DEBUG); 1928*912701f9SAndroid Build Coastguard Worker } 1929*912701f9SAndroid Build Coastguard Worker } elsif ($UPDATE_COUNT % 25 == 0) { 1930*912701f9SAndroid Build Coastguard Worker print " $UPDATE_COUNT..."; 1931*912701f9SAndroid Build Coastguard Worker } 1932*912701f9SAndroid Build Coastguard Worker ++$UPDATE_COUNT; 1933*912701f9SAndroid Build Coastguard Worker if ($relFile =~ m|/attic/|i) { 1934*912701f9SAndroid Build Coastguard Worker ++$UPDATE_ATTIC_COUNT; 1935*912701f9SAndroid Build Coastguard Worker } else { 1936*912701f9SAndroid Build Coastguard Worker ++$UPDATE_NONATTIC_COUNT; 1937*912701f9SAndroid Build Coastguard Worker } 1938*912701f9SAndroid Build Coastguard Worker my $f = "$CACHE/$relFile"; 1939*912701f9SAndroid Build Coastguard Worker command("rlog $CVSROOT/$relFile > $f", $f); 1940*912701f9SAndroid Build Coastguard Worker my $size = -s $f; 1941*912701f9SAndroid Build Coastguard Worker if ($size <= 0) { 1942*912701f9SAndroid Build Coastguard Worker print " <B>{Fatal Error: rlog of $relFile failed}</B> "; 1943*912701f9SAndroid Build Coastguard Worker unlink($f); 1944*912701f9SAndroid Build Coastguard Worker } 1945*912701f9SAndroid Build Coastguard Worker command("touch -r $CVSROOT/$relFile $f"); 1946*912701f9SAndroid Build Coastguard Worker } 1947*912701f9SAndroid Build Coastguard Worker} 1948*912701f9SAndroid Build Coastguard Worker 1949*912701f9SAndroid Build Coastguard Worker###################################################################### 1950*912701f9SAndroid Build Coastguard Worker# instaCache 1951*912701f9SAndroid Build Coastguard Worker###################################################################### 1952*912701f9SAndroid Build Coastguard Worker 1953*912701f9SAndroid Build Coastguard Worker#--------------------------------------------------------------------- 1954*912701f9SAndroid Build Coastguard Worker# Lookup an ID in the instaCache, and return the diffs stored 1955*912701f9SAndroid Build Coastguard Worker# there. If there is no entry for the ID, then return the 1956*912701f9SAndroid Build Coastguard Worker# empty string. The ID will be suffixed with 'a' if the 1957*912701f9SAndroid Build Coastguard Worker# Attic is included. 1958*912701f9SAndroid Build Coastguard Workersub instaGet { 1959*912701f9SAndroid Build Coastguard Worker my $id = shift; 1960*912701f9SAndroid Build Coastguard Worker my $diffs; 1961*912701f9SAndroid Build Coastguard Worker my $dir = $QUERY->param('include_attic') ? $INSTA_ATTIC : $INSTA; 1962*912701f9SAndroid Build Coastguard Worker my $file = "$dir/$id"; 1963*912701f9SAndroid Build Coastguard Worker if (-e $file) { 1964*912701f9SAndroid Build Coastguard Worker if (open(IN, $file)) { 1965*912701f9SAndroid Build Coastguard Worker while (<IN>) { $diffs .= $_; } 1966*912701f9SAndroid Build Coastguard Worker close(IN); 1967*912701f9SAndroid Build Coastguard Worker } 1968*912701f9SAndroid Build Coastguard Worker } 1969*912701f9SAndroid Build Coastguard Worker return $diffs; 1970*912701f9SAndroid Build Coastguard Worker} 1971*912701f9SAndroid Build Coastguard Worker 1972*912701f9SAndroid Build Coastguard Worker#--------------------------------------------------------------------- 1973*912701f9SAndroid Build Coastguard Worker# Store diffs for the given ID in the instaCache. The ID will be 1974*912701f9SAndroid Build Coastguard Worker# suffixed with 'a' if the Attic is included. 1975*912701f9SAndroid Build Coastguard Workersub instaPut { 1976*912701f9SAndroid Build Coastguard Worker my $id = shift; 1977*912701f9SAndroid Build Coastguard Worker my $diffs = shift; 1978*912701f9SAndroid Build Coastguard Worker my $dir = $QUERY->param('include_attic') ? $INSTA_ATTIC : $INSTA; 1979*912701f9SAndroid Build Coastguard Worker my $file = "$dir/$id"; 1980*912701f9SAndroid Build Coastguard Worker open(IN, ">$file") or return; 1981*912701f9SAndroid Build Coastguard Worker print IN $diffs; 1982*912701f9SAndroid Build Coastguard Worker close(IN); 1983*912701f9SAndroid Build Coastguard Worker} 1984*912701f9SAndroid Build Coastguard Worker 1985*912701f9SAndroid Build Coastguard Worker#--------------------------------------------------------------------- 1986*912701f9SAndroid Build Coastguard Worker# Reset the instaCache by deleting all entries. We need 1987*912701f9SAndroid Build Coastguard Worker# to do this whenever the main cache is invalidated. 1988*912701f9SAndroid Build Coastguard Worker# Param: if true, then force reset of all instaCaches. 1989*912701f9SAndroid Build Coastguard Worker# Otherwise do a smart reset based on the update counts. 1990*912701f9SAndroid Build Coastguard Workersub resetInstaCache { 1991*912701f9SAndroid Build Coastguard Worker if (shift) { 1992*912701f9SAndroid Build Coastguard Worker command("rm -rf $INSTA"); # Recursive 1993*912701f9SAndroid Build Coastguard Worker return; 1994*912701f9SAndroid Build Coastguard Worker } 1995*912701f9SAndroid Build Coastguard Worker 1996*912701f9SAndroid Build Coastguard Worker # If there have been changes to non-Attic files, we 1997*912701f9SAndroid Build Coastguard Worker # have to reset everything. 1998*912701f9SAndroid Build Coastguard Worker if ($UPDATE_NONATTIC_COUNT) { 1999*912701f9SAndroid Build Coastguard Worker # The following will fail with: 2000*912701f9SAndroid Build Coastguard Worker # rm: cannot remove `/tmp/icu-grepj.cache/insta/Attic': Is a directory 2001*912701f9SAndroid Build Coastguard Worker #command("rm -f $INSTA/*") if (-d $INSTA); 2002*912701f9SAndroid Build Coastguard Worker command("find $INSTA -type f -maxdepth 1 -exec rm {} \\;") 2003*912701f9SAndroid Build Coastguard Worker if (-d $INSTA); 2004*912701f9SAndroid Build Coastguard Worker } else { 2005*912701f9SAndroid Build Coastguard Worker # Otherwise just clear the attic instaCache 2006*912701f9SAndroid Build Coastguard Worker command("rm -f $INSTA_ATTIC/*") if (-d $INSTA_ATTIC); 2007*912701f9SAndroid Build Coastguard Worker } 2008*912701f9SAndroid Build Coastguard Worker} 2009*912701f9SAndroid Build Coastguard Worker 2010*912701f9SAndroid Build Coastguard Worker###################################################################### 2011*912701f9SAndroid Build Coastguard Worker# CVS Utilities 2012*912701f9SAndroid Build Coastguard Worker###################################################################### 2013*912701f9SAndroid Build Coastguard Worker 2014*912701f9SAndroid Build Coastguard Worker#--------------------------------------------------------------------- 2015*912701f9SAndroid Build Coastguard Worker# Get the date corresponding to the revision 1.1 in the 2016*912701f9SAndroid Build Coastguard Worker# given rlog output. We use this as the "creation date" for the 2017*912701f9SAndroid Build Coastguard Worker# corresponding CVS file. 2018*912701f9SAndroid Build Coastguard Worker# @param absolute rlog output file path (in the cache) 2019*912701f9SAndroid Build Coastguard Worker# @return date string of the form "2002/08/23 23:21:38" 2020*912701f9SAndroid Build Coastguard Workersub getRev11Date { 2021*912701f9SAndroid Build Coastguard Worker my $file = shift; 2022*912701f9SAndroid Build Coastguard Worker 2023*912701f9SAndroid Build Coastguard Worker # Parse the rlog file. Return the date line for 1.1 2024*912701f9SAndroid Build Coastguard Worker open(IN, $file); 2025*912701f9SAndroid Build Coastguard Worker while (<IN>) { 2026*912701f9SAndroid Build Coastguard Worker if (/^-{20,}$/) { 2027*912701f9SAndroid Build Coastguard Worker $_ = <IN>; 2028*912701f9SAndroid Build Coastguard Worker if (/revision 1.1$/) { 2029*912701f9SAndroid Build Coastguard Worker $_ = <IN>; 2030*912701f9SAndroid Build Coastguard Worker if (/^date: (.+?);/) { 2031*912701f9SAndroid Build Coastguard Worker return $1; 2032*912701f9SAndroid Build Coastguard Worker } 2033*912701f9SAndroid Build Coastguard Worker } 2034*912701f9SAndroid Build Coastguard Worker } 2035*912701f9SAndroid Build Coastguard Worker } 2036*912701f9SAndroid Build Coastguard Worker close(IN); 2037*912701f9SAndroid Build Coastguard Worker 2038*912701f9SAndroid Build Coastguard Worker ''; # Parse failure - should never happen 2039*912701f9SAndroid Build Coastguard Worker} 2040*912701f9SAndroid Build Coastguard Worker 2041*912701f9SAndroid Build Coastguard Worker#--------------------------------------------------------------------- 2042*912701f9SAndroid Build Coastguard Worker# Given a ,v file, find the revisions containing the 2043*912701f9SAndroid Build Coastguard Worker# jitterbug ID change. Return an array of hash refs. 2044*912701f9SAndroid Build Coastguard Worker# Newest revision is first, that is, it is $result[0]. 2045*912701f9SAndroid Build Coastguard Worker# Each hash has: 2046*912701f9SAndroid Build Coastguard Worker# new (revision#) 2047*912701f9SAndroid Build Coastguard Worker# old (revision#) 2048*912701f9SAndroid Build Coastguard Worker# date 2049*912701f9SAndroid Build Coastguard Worker# author 2050*912701f9SAndroid Build Coastguard Worker# comment 2051*912701f9SAndroid Build Coastguard Worker# If the very first revision is labeled with the jitterbug 2052*912701f9SAndroid Build Coastguard Worker# $ID, then {old} will be $BASE_REV. 2053*912701f9SAndroid Build Coastguard Worker# 2054*912701f9SAndroid Build Coastguard Workersub findRevisions { 2055*912701f9SAndroid Build Coastguard Worker my $file = shift; 2056*912701f9SAndroid Build Coastguard Worker my $pat = shift; 2057*912701f9SAndroid Build Coastguard Worker my @result; 2058*912701f9SAndroid Build Coastguard Worker 2059*912701f9SAndroid Build Coastguard Worker # rlog output: 2060*912701f9SAndroid Build Coastguard Worker #|revision 1.3 2061*912701f9SAndroid Build Coastguard Worker #|date: 1999/10/14 22:14:04; author: schererm; state: Exp; lines: +4 -2 2062*912701f9SAndroid Build Coastguard Worker #|jitterbug 14: echo off now and use the Release versions of the tools 2063*912701f9SAndroid Build Coastguard Worker #|---------------------------- 2064*912701f9SAndroid Build Coastguard Worker #|revision 1.2 2065*912701f9SAndroid Build Coastguard Worker #|date: 1999/10/13 01:10:24; author: schererm; state: Exp; lines: +9 -6 2066*912701f9SAndroid Build Coastguard Worker #|jitterbug 15: windows: genrb puts .res files into the current directory 2067*912701f9SAndroid Build Coastguard Worker #|more text 2068*912701f9SAndroid Build Coastguard Worker #|---------------------------- 2069*912701f9SAndroid Build Coastguard Worker #|revision 1.1 2070*912701f9SAndroid Build Coastguard Worker #|date: 1999/10/12 21:50:30; author: schererm; state: Exp; 2071*912701f9SAndroid Build Coastguard Worker #|jitterbug 14: Windows: create a batch file to make the /icu/data files 2072*912701f9SAndroid Build Coastguard Worker #|============================================================================= 2073*912701f9SAndroid Build Coastguard Worker 2074*912701f9SAndroid Build Coastguard Worker # We read our rlog info from the cache now 2075*912701f9SAndroid Build Coastguard Worker my %log; # $log{<revision>} = <block of text> 2076*912701f9SAndroid Build Coastguard Worker my $l=''; my $r=''; 2077*912701f9SAndroid Build Coastguard Worker open(IN, $file); 2078*912701f9SAndroid Build Coastguard Worker while (<IN>) { 2079*912701f9SAndroid Build Coastguard Worker if (/^-{20,}$/) { 2080*912701f9SAndroid Build Coastguard Worker $log{$r} = $l if ($r); 2081*912701f9SAndroid Build Coastguard Worker $l = $r = ''; 2082*912701f9SAndroid Build Coastguard Worker } elsif ($r) { 2083*912701f9SAndroid Build Coastguard Worker $l .= $_; 2084*912701f9SAndroid Build Coastguard Worker } else { 2085*912701f9SAndroid Build Coastguard Worker if (/revision\s+(\S+)/) { 2086*912701f9SAndroid Build Coastguard Worker $r = $1; 2087*912701f9SAndroid Build Coastguard Worker die "Duplicate revision $r in $file" if (exists $log{$r}); 2088*912701f9SAndroid Build Coastguard Worker } 2089*912701f9SAndroid Build Coastguard Worker } 2090*912701f9SAndroid Build Coastguard Worker } 2091*912701f9SAndroid Build Coastguard Worker close(IN); 2092*912701f9SAndroid Build Coastguard Worker $log{$r} = $l if ($r); 2093*912701f9SAndroid Build Coastguard Worker 2094*912701f9SAndroid Build Coastguard Worker for $r (sort cmprevs keys %log) { 2095*912701f9SAndroid Build Coastguard Worker local $_ = $log{$r}; 2096*912701f9SAndroid Build Coastguard Worker 2097*912701f9SAndroid Build Coastguard Worker # (2 of 3 REGEXPS) SEE ALSO other regexps; keep them in sync 2098*912701f9SAndroid Build Coastguard Worker if (/^\s*(?:$CVS_MSG_KW)\s*$pat\b/im) { 2099*912701f9SAndroid Build Coastguard Worker my %h; 2100*912701f9SAndroid Build Coastguard Worker $h{new} = $r; 2101*912701f9SAndroid Build Coastguard Worker my $rold = decRev($r); 2102*912701f9SAndroid Build Coastguard Worker if (exists $log{$rold}) { 2103*912701f9SAndroid Build Coastguard Worker $h{old} = $rold; 2104*912701f9SAndroid Build Coastguard Worker } else { 2105*912701f9SAndroid Build Coastguard Worker $h{old} = $BASE_REV; 2106*912701f9SAndroid Build Coastguard Worker } 2107*912701f9SAndroid Build Coastguard Worker if (/date:\s*(.+?);/) { 2108*912701f9SAndroid Build Coastguard Worker $h{date} = $1; 2109*912701f9SAndroid Build Coastguard Worker } 2110*912701f9SAndroid Build Coastguard Worker if (/author:\s*(.+?);/) { 2111*912701f9SAndroid Build Coastguard Worker $h{author} = $1; 2112*912701f9SAndroid Build Coastguard Worker } 2113*912701f9SAndroid Build Coastguard Worker 2114*912701f9SAndroid Build Coastguard Worker # (3 of 3 REGEXPS) SEE ALSO other regexps; keep them in sync 2115*912701f9SAndroid Build Coastguard Worker if (/^\s*(?:$CVS_MSG_KW)\s*$pat\b(.*)/ism) { 2116*912701f9SAndroid Build Coastguard Worker local $_ = $1; 2117*912701f9SAndroid Build Coastguard Worker s/^\s*:?\s*//; 2118*912701f9SAndroid Build Coastguard Worker s/\s*----+\s*$//; 2119*912701f9SAndroid Build Coastguard Worker s/\s*====+\s*$//; 2120*912701f9SAndroid Build Coastguard Worker s/\s*\n+\s*/ /g; 2121*912701f9SAndroid Build Coastguard Worker $h{comment} = $_; 2122*912701f9SAndroid Build Coastguard Worker } 2123*912701f9SAndroid Build Coastguard Worker push @result, \%h; 2124*912701f9SAndroid Build Coastguard Worker } 2125*912701f9SAndroid Build Coastguard Worker } 2126*912701f9SAndroid Build Coastguard Worker 2127*912701f9SAndroid Build Coastguard Worker @result; 2128*912701f9SAndroid Build Coastguard Worker} 2129*912701f9SAndroid Build Coastguard Worker 2130*912701f9SAndroid Build Coastguard Worker###################################################################### 2131*912701f9SAndroid Build Coastguard Worker# CVS tag parsing 2132*912701f9SAndroid Build Coastguard Worker###################################################################### 2133*912701f9SAndroid Build Coastguard Worker 2134*912701f9SAndroid Build Coastguard Worker#--------------------------------------------------------------------- 2135*912701f9SAndroid Build Coastguard Worker# Given a tag name like this: "2.1", expand it to "release-2-1". 2136*912701f9SAndroid Build Coastguard Worker# Convert 'head' (case insens.) to 'HEAD'. 2137*912701f9SAndroid Build Coastguard Worker# Otherwise leave it alone. 2138*912701f9SAndroid Build Coastguard Workersub expandTag { 2139*912701f9SAndroid Build Coastguard Worker local $_ = shift; 2140*912701f9SAndroid Build Coastguard Worker s/^\s+//; 2141*912701f9SAndroid Build Coastguard Worker s/\s+$//; 2142*912701f9SAndroid Build Coastguard Worker if (/^\d+(\.\d+)/) { 2143*912701f9SAndroid Build Coastguard Worker s|\.|-|g; 2144*912701f9SAndroid Build Coastguard Worker $_ = "release-" . $_; 2145*912701f9SAndroid Build Coastguard Worker } elsif (/^head$/i) { 2146*912701f9SAndroid Build Coastguard Worker $_ = 'HEAD'; 2147*912701f9SAndroid Build Coastguard Worker } 2148*912701f9SAndroid Build Coastguard Worker $_; 2149*912701f9SAndroid Build Coastguard Worker} 2150*912701f9SAndroid Build Coastguard Worker 2151*912701f9SAndroid Build Coastguard Worker#--------------------------------------------------------------------- 2152*912701f9SAndroid Build Coastguard Worker# Given a tag name like this: "release-1-5-0-d03", return a normalized 2153*912701f9SAndroid Build Coastguard Worker# release number. The release number in this case would be 1500003. 2154*912701f9SAndroid Build Coastguard Worker# The final release (no 'd') "release-1-5-0" is 1500099; that is, it 2155*912701f9SAndroid Build Coastguard Worker# behaves like "d99". Up to 5 digits are allowed prior to the 'd' 2156*912701f9SAndroid Build Coastguard Worker# number (if any). This should suffice; in practice we use only 4 2157*912701f9SAndroid Build Coastguard Worker# (e.g., "release-1-4-1-2"). Assume all numbers are single digits 2158*912701f9SAndroid Build Coastguard Worker# except for the 'd' number. The tag must start with /release-?/. 2159*912701f9SAndroid Build Coastguard Worker# All digits must be separated by '-', except the '-' before the 'd03' 2160*912701f9SAndroid Build Coastguard Worker# may be omitted. One or two digits are allowed after the 'd'. 2161*912701f9SAndroid Build Coastguard Worker# Trailing text after an otherwise valid tag, with no 'd', is treated 2162*912701f9SAndroid Build Coastguard Worker# as a 'd' of 00, e.g., "release-2-0-2s-branch". 2163*912701f9SAndroid Build Coastguard Worker# 2164*912701f9SAndroid Build Coastguard Worker# @param a tag string, like "release-1-5-0-d03" 2165*912701f9SAndroid Build Coastguard Worker# @param a release integer, that can be compared numerically, 2166*912701f9SAndroid Build Coastguard Worker# like 1500003, or if the tag can't be parsed. 2167*912701f9SAndroid Build Coastguard Workersub tagToRelease { 2168*912701f9SAndroid Build Coastguard Worker local $_ = shift; 2169*912701f9SAndroid Build Coastguard Worker if (s/^release-?//i) { 2170*912701f9SAndroid Build Coastguard Worker my @a; 2171*912701f9SAndroid Build Coastguard Worker my $d = -1; 2172*912701f9SAndroid Build Coastguard Worker for (;;) { 2173*912701f9SAndroid Build Coastguard Worker if (s/^(\d)-// || 2174*912701f9SAndroid Build Coastguard Worker s/^(\d)$// || 2175*912701f9SAndroid Build Coastguard Worker s/(\d)(\D)/$2/) { # e.g., "release-1-4-2d01" 2176*912701f9SAndroid Build Coastguard Worker push @a, $1; 2177*912701f9SAndroid Build Coastguard Worker } elsif ($d<0 && s/^d(\d{1,2})$//) { 2178*912701f9SAndroid Build Coastguard Worker $d = $1; 2179*912701f9SAndroid Build Coastguard Worker } else { 2180*912701f9SAndroid Build Coastguard Worker last; 2181*912701f9SAndroid Build Coastguard Worker } 2182*912701f9SAndroid Build Coastguard Worker } 2183*912701f9SAndroid Build Coastguard Worker # If we have some trailing non-standard text, and no 'd', 2184*912701f9SAndroid Build Coastguard Worker # then treat it as a 'd' of 00. 2185*912701f9SAndroid Build Coastguard Worker if ($_ && $d<0 && (scalar @a)>0) { 2186*912701f9SAndroid Build Coastguard Worker $_ = ''; 2187*912701f9SAndroid Build Coastguard Worker $d = 0; 2188*912701f9SAndroid Build Coastguard Worker } 2189*912701f9SAndroid Build Coastguard Worker if (!$_) { 2190*912701f9SAndroid Build Coastguard Worker push @a, (0, 0, 0, 0); # Pad with 0's 2191*912701f9SAndroid Build Coastguard Worker @a = @a[0..4]; 2192*912701f9SAndroid Build Coastguard Worker return join('',@a) . sprintf("%02d", $d<0?99:$d); 2193*912701f9SAndroid Build Coastguard Worker } 2194*912701f9SAndroid Build Coastguard Worker } 2195*912701f9SAndroid Build Coastguard Worker 0; # parse failure 2196*912701f9SAndroid Build Coastguard Worker} 2197*912701f9SAndroid Build Coastguard Worker 2198*912701f9SAndroid Build Coastguard Worker###################################################################### 2199*912701f9SAndroid Build Coastguard Worker# Utilities 2200*912701f9SAndroid Build Coastguard Worker###################################################################### 2201*912701f9SAndroid Build Coastguard Worker 2202*912701f9SAndroid Build Coastguard Worker# Output a string in debug mode 2203*912701f9SAndroid Build Coastguard Worker# Usage: debugOut("string") if ($DEBUG); 2204*912701f9SAndroid Build Coastguard Workersub debugOut { 2205*912701f9SAndroid Build Coastguard Worker print "<P><FONT SIZE=-1><B>", join(" ", @_), "</B></FONT></P>"; 2206*912701f9SAndroid Build Coastguard Worker} 2207*912701f9SAndroid Build Coastguard Worker 2208*912701f9SAndroid Build Coastguard Worker#|# Set or change a GET param of a URL. If the param exists, 2209*912701f9SAndroid Build Coastguard Worker#|# change it. If it doesn't, add it. 2210*912701f9SAndroid Build Coastguard Worker#|# @param a URL, with or without trailing parameters 2211*912701f9SAndroid Build Coastguard Worker#|# @param a parameter string of the form a=b, a=, or a 2212*912701f9SAndroid Build Coastguard Worker#|# @param modified URL 2213*912701f9SAndroid Build Coastguard Worker#|sub urlParam { 2214*912701f9SAndroid Build Coastguard Worker#| my $url = shift; 2215*912701f9SAndroid Build Coastguard Worker#| my $param = shift; 2216*912701f9SAndroid Build Coastguard Worker#| my $key = $param; 2217*912701f9SAndroid Build Coastguard Worker#| $key =~ s/=.*//; 2218*912701f9SAndroid Build Coastguard Worker#| if ($url =~ s/([\?&;])$key=[^&;]*/$1$param/ || 2219*912701f9SAndroid Build Coastguard Worker#| $url =~ s/([\?&;])$key$/$1$param/) { 2220*912701f9SAndroid Build Coastguard Worker#| return $url; 2221*912701f9SAndroid Build Coastguard Worker#| } 2222*912701f9SAndroid Build Coastguard Worker#| $url . ($url =~ /\?/ ? '&' : '?') . $param; 2223*912701f9SAndroid Build Coastguard Worker#|} 2224*912701f9SAndroid Build Coastguard Worker 2225*912701f9SAndroid Build Coastguard Worker# Append the given path-info to the given URL 2226*912701f9SAndroid Build Coastguard Worker# Param: URL, possibly including '?xxx=yyy' params, NOT ending in '/' 2227*912701f9SAndroid Build Coastguard Worker# Param: Path info, MUST start with '/' 2228*912701f9SAndroid Build Coastguard Workersub urlPathInfo { 2229*912701f9SAndroid Build Coastguard Worker my $url = shift; 2230*912701f9SAndroid Build Coastguard Worker my $pi = shift; 2231*912701f9SAndroid Build Coastguard Worker if ($url =~ s|\?|$pi?|) { 2232*912701f9SAndroid Build Coastguard Worker } else { 2233*912701f9SAndroid Build Coastguard Worker $url .= $pi; 2234*912701f9SAndroid Build Coastguard Worker } 2235*912701f9SAndroid Build Coastguard Worker $url; 2236*912701f9SAndroid Build Coastguard Worker} 2237*912701f9SAndroid Build Coastguard Worker 2238*912701f9SAndroid Build Coastguard Worker# Parse the module params given by the user 2239*912701f9SAndroid Build Coastguard Worker# @param ref to array to receive list of modules. Prior contents will 2240*912701f9SAndroid Build Coastguard Worker# be lost. 2241*912701f9SAndroid Build Coastguard Worker# @return 1 on success, or 0 if bad or no modules were seen. 2242*912701f9SAndroid Build Coastguard Workersub parseMod { 2243*912701f9SAndroid Build Coastguard Worker my $m = shift; # ref to array 2244*912701f9SAndroid Build Coastguard Worker my @badMod; 2245*912701f9SAndroid Build Coastguard Worker 2246*912701f9SAndroid Build Coastguard Worker my $mod = $QUERY->param('mod') || $DEFAULT_MOD; 2247*912701f9SAndroid Build Coastguard Worker $mod =~ s|^\s+||; 2248*912701f9SAndroid Build Coastguard Worker $mod =~ s|\s+$||; 2249*912701f9SAndroid Build Coastguard Worker $mod =~ s|\s+| |g; 2250*912701f9SAndroid Build Coastguard Worker @$m = split(' ', $mod); 2251*912701f9SAndroid Build Coastguard Worker foreach (@$m) { 2252*912701f9SAndroid Build Coastguard Worker # !Modify element of @m in place! 2253*912701f9SAndroid Build Coastguard Worker $_ = $MOD_ABBREV{$_} if (exists $MOD_ABBREV{$_}); 2254*912701f9SAndroid Build Coastguard Worker push @badMod, $_ if (! -d "$CVSROOT/$_"); 2255*912701f9SAndroid Build Coastguard Worker } 2256*912701f9SAndroid Build Coastguard Worker if (@badMod) { 2257*912701f9SAndroid Build Coastguard Worker print "Invalid modules: <CODE>", 2258*912701f9SAndroid Build Coastguard Worker join(" ", @badMod), "</CODE>"; 2259*912701f9SAndroid Build Coastguard Worker print "<BR>Did you try the full module name (e.g. \"icu/charset\")? Only some modules can be abbreviated: <CODE>", join(" ", sort keys %MOD_ABBREV), "</CODE>."; 2260*912701f9SAndroid Build Coastguard Worker return 0; 2261*912701f9SAndroid Build Coastguard Worker } 2262*912701f9SAndroid Build Coastguard Worker 1; 2263*912701f9SAndroid Build Coastguard Worker} 2264*912701f9SAndroid Build Coastguard Worker 2265*912701f9SAndroid Build Coastguard Worker# Return the HTML for a link to the given jitterbug. 2266*912701f9SAndroid Build Coastguard Worker# @param user 2267*912701f9SAndroid Build Coastguard Worker# @param bug ID 2268*912701f9SAndroid Build Coastguard Worker# @param OPTIONAL target 2269*912701f9SAndroid Build Coastguard Worker# @return HTML for A tag 2270*912701f9SAndroid Build Coastguard Workersub jitterbugLink { 2271*912701f9SAndroid Build Coastguard Worker my $user = shift; 2272*912701f9SAndroid Build Coastguard Worker my $id = shift; 2273*912701f9SAndroid Build Coastguard Worker my $targ = shift || ''; 2274*912701f9SAndroid Build Coastguard Worker if ($id eq $NO_JITTERBUG) { 2275*912701f9SAndroid Build Coastguard Worker return "<EM>no jitterbug</EM>"; 2276*912701f9SAndroid Build Coastguard Worker } 2277*912701f9SAndroid Build Coastguard Worker $targ = " target=\"$targ\"" if ($targ); 2278*912701f9SAndroid Build Coastguard Worker "<A href=\"" . jitterbugURL($user, $id) . "\"$targ>$id</A>"; 2279*912701f9SAndroid Build Coastguard Worker} 2280*912701f9SAndroid Build Coastguard Worker 2281*912701f9SAndroid Build Coastguard Worker# Return the HTML for a link to the WebCVS log of a file. 2282*912701f9SAndroid Build Coastguard Worker# @param relative path (from $CVSROOT) to file, optionally with 2283*912701f9SAndroid Build Coastguard Worker# trailing ",v" 2284*912701f9SAndroid Build Coastguard Worker# @param OPTIONAL target 2285*912701f9SAndroid Build Coastguard Worker# @return HTML for A tag 2286*912701f9SAndroid Build Coastguard Workersub logLink { 2287*912701f9SAndroid Build Coastguard Worker my $relFile = shift; 2288*912701f9SAndroid Build Coastguard Worker my $targ = shift; 2289*912701f9SAndroid Build Coastguard Worker $targ = " target=\"$targ\"" if ($targ); 2290*912701f9SAndroid Build Coastguard Worker $relFile =~ s/,v$//; 2291*912701f9SAndroid Build Coastguard Worker "<A href=\"$LOG_URL/$relFile\"$targ>$relFile</A>"; 2292*912701f9SAndroid Build Coastguard Worker} 2293*912701f9SAndroid Build Coastguard Worker 2294*912701f9SAndroid Build Coastguard Worker# Return the HTML for a link to the WebCVS "tag" page. This will 2295*912701f9SAndroid Build Coastguard Worker# just be the page for the root of the given module, with the given 2296*912701f9SAndroid Build Coastguard Worker# tag selected. 2297*912701f9SAndroid Build Coastguard Worker# @param tag 2298*912701f9SAndroid Build Coastguard Worker# @param module, e.g., "icu/icu" 2299*912701f9SAndroid Build Coastguard Worker# @param OPTIONAL target 2300*912701f9SAndroid Build Coastguard Worker# @return HTML for A tag 2301*912701f9SAndroid Build Coastguard Workersub tagLink { 2302*912701f9SAndroid Build Coastguard Worker my $tag = shift; 2303*912701f9SAndroid Build Coastguard Worker my $mod = shift; 2304*912701f9SAndroid Build Coastguard Worker my $targ = shift; 2305*912701f9SAndroid Build Coastguard Worker $targ = " target=\"$targ\"" if ($targ); 2306*912701f9SAndroid Build Coastguard Worker "<A href=\"$LOG_URL/$mod/?only_with_tag=$tag\"$targ>$tag</A>"; 2307*912701f9SAndroid Build Coastguard Worker} 2308*912701f9SAndroid Build Coastguard Worker 2309*912701f9SAndroid Build Coastguard Worker# Emit an error (in HTML) about failing to parse a line. 2310*912701f9SAndroid Build Coastguard Worker# @param what can't be parsed, e.g., 'revision' 2311*912701f9SAndroid Build Coastguard Worker# @param relative file path, e.g., 'icu/icu/readme.html' 2312*912701f9SAndroid Build Coastguard Worker# @param the line that can't be parsed 2313*912701f9SAndroid Build Coastguard Worker# @param revision 2314*912701f9SAndroid Build Coastguard Workersub cantParse { 2315*912701f9SAndroid Build Coastguard Worker my $what = shift; 2316*912701f9SAndroid Build Coastguard Worker my $relFile = shift; 2317*912701f9SAndroid Build Coastguard Worker my $line = shift; 2318*912701f9SAndroid Build Coastguard Worker my $rev = shift; 2319*912701f9SAndroid Build Coastguard Worker $rev = ', '.$rev if ($rev); 2320*912701f9SAndroid Build Coastguard Worker print "<BR>Error: Can't parse $what in " 2321*912701f9SAndroid Build Coastguard Worker , logLink($relFile, 'grepj_2'), "$rev:<BR>\n"; 2322*912701f9SAndroid Build Coastguard Worker print "<CODE>$line</CODE><BR>"; 2323*912701f9SAndroid Build Coastguard Worker} 2324*912701f9SAndroid Build Coastguard Worker 2325*912701f9SAndroid Build Coastguard Worker# Print the given string(s) to STDOUT and also return the 2326*912701f9SAndroid Build Coastguard Worker# output as a single string. 2327*912701f9SAndroid Build Coastguard Workersub out { 2328*912701f9SAndroid Build Coastguard Worker local $_ = join('', @_); 2329*912701f9SAndroid Build Coastguard Worker print; 2330*912701f9SAndroid Build Coastguard Worker $_; 2331*912701f9SAndroid Build Coastguard Worker} 2332*912701f9SAndroid Build Coastguard Worker 2333*912701f9SAndroid Build Coastguard Worker# Given an array of numbers, return a sorted unique list. 2334*912701f9SAndroid Build Coastguard Workersub sortedUniqueInts { 2335*912701f9SAndroid Build Coastguard Worker my @a = @_; 2336*912701f9SAndroid Build Coastguard Worker my %a; 2337*912701f9SAndroid Build Coastguard Worker foreach (@a) { 2338*912701f9SAndroid Build Coastguard Worker s/^0+(\d)/$1/; 2339*912701f9SAndroid Build Coastguard Worker $a{$_} = 1; 2340*912701f9SAndroid Build Coastguard Worker } 2341*912701f9SAndroid Build Coastguard Worker sort {$a<=>$b} keys %a; 2342*912701f9SAndroid Build Coastguard Worker} 2343*912701f9SAndroid Build Coastguard Worker 2344*912701f9SAndroid Build Coastguard Worker# Convert a revision number to a branch number. 2345*912701f9SAndroid Build Coastguard Worker# Generally this means dropping the last dotted integer, but if 2346*912701f9SAndroid Build Coastguard Worker# the last two dotted integers are 0.n, then the 0. must be dropped: 2347*912701f9SAndroid Build Coastguard Worker# 1.14.0.2 => 1.14.2. (This is a magic CVS revision representing 2348*912701f9SAndroid Build Coastguard Worker# the branch.) Also 'HEAD' is branch '1'. 2349*912701f9SAndroid Build Coastguard Workersub revToBranch { 2350*912701f9SAndroid Build Coastguard Worker local $_ = shift; 2351*912701f9SAndroid Build Coastguard Worker s/\.0(\.\d+)$/$1/ || s/\.\d+$// || s/HEAD/1/; 2352*912701f9SAndroid Build Coastguard Worker $_; 2353*912701f9SAndroid Build Coastguard Worker} 2354*912701f9SAndroid Build Coastguard Worker 2355*912701f9SAndroid Build Coastguard Worker# Given two CVS revisions, return a sequence of revisions traversing 2356*912701f9SAndroid Build Coastguard Worker# the logical path between them. 2357*912701f9SAndroid Build Coastguard Worker# 2358*912701f9SAndroid Build Coastguard Worker# WARNING!: The revisions must actually have a path between them. If 2359*912701f9SAndroid Build Coastguard Worker# you pass in 1.4 => 1.2 or 1.5 => 1.2.2.4 the sub will run 2360*912701f9SAndroid Build Coastguard Worker# infinitely. 2361*912701f9SAndroid Build Coastguard Worker# 2362*912701f9SAndroid Build Coastguard Worker# @param low revision, e.g. 1.2 or 1.2.0.4 2363*912701f9SAndroid Build Coastguard Worker# @param high revision, e.g., 1.5.2.3 2364*912701f9SAndroid Build Coastguard Worker# @return an array of revisions from low to high inclusive 2365*912701f9SAndroid Build Coastguard Workersub traverseRevisions { 2366*912701f9SAndroid Build Coastguard Worker my $rev_lo = shift; 2367*912701f9SAndroid Build Coastguard Worker my $rev_hi = shift; 2368*912701f9SAndroid Build Coastguard Worker my @a = split(/\./, $rev_lo); 2369*912701f9SAndroid Build Coastguard Worker my @limit = split(/\./, $rev_hi); 2370*912701f9SAndroid Build Coastguard Worker my @list; 2371*912701f9SAndroid Build Coastguard Worker for (;;) { 2372*912701f9SAndroid Build Coastguard Worker push @list, join('.', @a); 2373*912701f9SAndroid Build Coastguard Worker if (@a == @limit) { 2374*912701f9SAndroid Build Coastguard Worker last if ($a[-1] == $limit[-1]); 2375*912701f9SAndroid Build Coastguard Worker # Fall through 2376*912701f9SAndroid Build Coastguard Worker } else { 2377*912701f9SAndroid Build Coastguard Worker my $a = join('.', @a); 2378*912701f9SAndroid Build Coastguard Worker if ($rev_hi =~ /^\Q$a\E\./) { 2379*912701f9SAndroid Build Coastguard Worker push @a, $limit[@a]; 2380*912701f9SAndroid Build Coastguard Worker push @a, 1; 2381*912701f9SAndroid Build Coastguard Worker next; 2382*912701f9SAndroid Build Coastguard Worker } 2383*912701f9SAndroid Build Coastguard Worker # Else fall through 2384*912701f9SAndroid Build Coastguard Worker } 2385*912701f9SAndroid Build Coastguard Worker 2386*912701f9SAndroid Build Coastguard Worker if ($a[-2] == 0) { 2387*912701f9SAndroid Build Coastguard Worker # Handle magic CVS revisions like 1.14.0.2 2388*912701f9SAndroid Build Coastguard Worker $a[-2] = $a[-1]; 2389*912701f9SAndroid Build Coastguard Worker $a[-1] = 1; 2390*912701f9SAndroid Build Coastguard Worker } else { 2391*912701f9SAndroid Build Coastguard Worker $a[-1]++; 2392*912701f9SAndroid Build Coastguard Worker } 2393*912701f9SAndroid Build Coastguard Worker } 2394*912701f9SAndroid Build Coastguard Worker @list; 2395*912701f9SAndroid Build Coastguard Worker} 2396*912701f9SAndroid Build Coastguard Worker 2397*912701f9SAndroid Build Coastguard Worker# Given a CVS numeric revision, increment it (increment last integer) 2398*912701f9SAndroid Build Coastguard Workersub incRev { 2399*912701f9SAndroid Build Coastguard Worker local $_ = shift; 2400*912701f9SAndroid Build Coastguard Worker if (/(\d+)$/) { 2401*912701f9SAndroid Build Coastguard Worker my $i = $1 + 1; 2402*912701f9SAndroid Build Coastguard Worker s/\d+$/$i/; 2403*912701f9SAndroid Build Coastguard Worker return $_; 2404*912701f9SAndroid Build Coastguard Worker } 2405*912701f9SAndroid Build Coastguard Worker die "Can't increment $_"; 2406*912701f9SAndroid Build Coastguard Worker} 2407*912701f9SAndroid Build Coastguard Worker 2408*912701f9SAndroid Build Coastguard Worker# Given a CVS numeric revisions, decrement it. This handles 2409*912701f9SAndroid Build Coastguard Worker# branches. If the resulting revision number goes to zero, 2410*912701f9SAndroid Build Coastguard Worker# return BASE_REV. Does not handle magic revisions like 1.14.0.2. 2411*912701f9SAndroid Build Coastguard Worker# 1.3 => 1.2 2412*912701f9SAndroid Build Coastguard Worker# 1.3.2.1 => 1.3 2413*912701f9SAndroid Build Coastguard Worker# 1.3.2.2 => 1.3.2.1 2414*912701f9SAndroid Build Coastguard Workersub decRev { 2415*912701f9SAndroid Build Coastguard Worker local $_ = shift; 2416*912701f9SAndroid Build Coastguard Worker if (/(\d+)$/) { 2417*912701f9SAndroid Build Coastguard Worker my $i = $1 - 1; 2418*912701f9SAndroid Build Coastguard Worker if ($i >= 1) { 2419*912701f9SAndroid Build Coastguard Worker s/\d+$/$i/; 2420*912701f9SAndroid Build Coastguard Worker } elsif (s/(^1\.\d+)\.2\.1$/$1/) { 2421*912701f9SAndroid Build Coastguard Worker # 1.3.2.1 => 1.3 2422*912701f9SAndroid Build Coastguard Worker } else { 2423*912701f9SAndroid Build Coastguard Worker return $BASE_REV; 2424*912701f9SAndroid Build Coastguard Worker } 2425*912701f9SAndroid Build Coastguard Worker return $_; 2426*912701f9SAndroid Build Coastguard Worker } 2427*912701f9SAndroid Build Coastguard Worker die "Can't decrement $_"; 2428*912701f9SAndroid Build Coastguard Worker} 2429*912701f9SAndroid Build Coastguard Worker 2430*912701f9SAndroid Build Coastguard Worker# Given a date string, in CVS format, like "2003/05/29 22:10:17", 2431*912701f9SAndroid Build Coastguard Worker# return the duration $NOW - x, in days. 2432*912701f9SAndroid Build Coastguard Workersub ageInDays { 2433*912701f9SAndroid Build Coastguard Worker local $_ = shift; 2434*912701f9SAndroid Build Coastguard Worker if (m|(\d+)/(\d+)/(\d+)\s+(\d+):(\d+):(\d+)|) { 2435*912701f9SAndroid Build Coastguard Worker my ($y,$m,$d,$H,$M,$S) = ($1,$2-1,$3,$4,$5,$6); 2436*912701f9SAndroid Build Coastguard Worker if ($y =~ /^\d\d$/) { 2437*912701f9SAndroid Build Coastguard Worker $y = 100*int($YEAR / 100) + $y; 2438*912701f9SAndroid Build Coastguard Worker $y -= 100 if ($y > $YEAR); 2439*912701f9SAndroid Build Coastguard Worker } 2440*912701f9SAndroid Build Coastguard Worker return ($NOW - timelocal_nocheck($S,$M,$H,$d,$m,$y)) / 86400.0; 2441*912701f9SAndroid Build Coastguard Worker } else { 2442*912701f9SAndroid Build Coastguard Worker die "Can't parse date $_\n"; 2443*912701f9SAndroid Build Coastguard Worker } 2444*912701f9SAndroid Build Coastguard Worker} 2445*912701f9SAndroid Build Coastguard Worker 2446*912701f9SAndroid Build Coastguard Worker# Filter for which files we care about that don't have jitterbugs. 2447*912701f9SAndroid Build Coastguard Worker# Our rule is that if the checkin is over a year old, we don't care 2448*912701f9SAndroid Build Coastguard Worker# about it. We used to also require the revision to be 1.1 or 1.1.1.1 2449*912701f9SAndroid Build Coastguard Worker# to be ignored, but we dropped this. 2450*912701f9SAndroid Build Coastguard Workersub noJitterbugFilter { 2451*912701f9SAndroid Build Coastguard Worker my $rev = shift; 2452*912701f9SAndroid Build Coastguard Worker my $date = shift; 2453*912701f9SAndroid Build Coastguard Worker #if ($rev eq '1.1' || $rev eq '1.1.1.1') { 2454*912701f9SAndroid Build Coastguard Worker return ageInDays($date) <= 365.25; 2455*912701f9SAndroid Build Coastguard Worker #} 2456*912701f9SAndroid Build Coastguard Worker #1; 2457*912701f9SAndroid Build Coastguard Worker} 2458*912701f9SAndroid Build Coastguard Worker 2459*912701f9SAndroid Build Coastguard Worker# Execute a command, trapping errors. 2460*912701f9SAndroid Build Coastguard Worker# Options second arg: Path to a file to delete upon failure 2461*912701f9SAndroid Build Coastguard Workersub command { 2462*912701f9SAndroid Build Coastguard Worker my $cmd = shift; 2463*912701f9SAndroid Build Coastguard Worker my $fileToDeleteOnFailure = shift; 2464*912701f9SAndroid Build Coastguard Worker 2465*912701f9SAndroid Build Coastguard Worker my $err = "$CACHE/grepj.stderr"; 2466*912701f9SAndroid Build Coastguard Worker my $status = system($cmd . " 2> $err"); 2467*912701f9SAndroid Build Coastguard Worker if ($status != 0) { 2468*912701f9SAndroid Build Coastguard Worker unlink($fileToDeleteOnFailure) if defined($fileToDeleteOnFailure); 2469*912701f9SAndroid Build Coastguard Worker print "<HR><B>Fatal Error: " 2470*912701f9SAndroid Build Coastguard Worker . "\"$cmd\" exited with value " 2471*912701f9SAndroid Build Coastguard Worker . ($status >> 8) 2472*912701f9SAndroid Build Coastguard Worker . " (signal " . ($status & 127) . ")" 2473*912701f9SAndroid Build Coastguard Worker . (($status & 128) ? " (core dumped)" : "") 2474*912701f9SAndroid Build Coastguard Worker . "<BR></B>"; 2475*912701f9SAndroid Build Coastguard Worker print "stderr:<BR>"; 2476*912701f9SAndroid Build Coastguard Worker if (open(IN, $err)) { 2477*912701f9SAndroid Build Coastguard Worker while (<IN>) { 2478*912701f9SAndroid Build Coastguard Worker print $_, "<BR>"; 2479*912701f9SAndroid Build Coastguard Worker } 2480*912701f9SAndroid Build Coastguard Worker close(IN); 2481*912701f9SAndroid Build Coastguard Worker } 2482*912701f9SAndroid Build Coastguard Worker croak "Couldn't execute \"$cmd\""; 2483*912701f9SAndroid Build Coastguard Worker } 2484*912701f9SAndroid Build Coastguard Worker} 2485*912701f9SAndroid Build Coastguard Worker 2486*912701f9SAndroid Build Coastguard Worker#eof 2487